bsv-bap 0.1.12 → 0.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -85,10 +85,25 @@ OP_RETURN
85
85
 
86
86
  Each identity possesses distinct keys for different operations:
87
87
 
88
- - **Signing Key**: Transaction authorization and message signing
88
+ - **Member Key**: The root key for each identity path, used for key derivation
89
+ - **Signing Key**: Derived from member key for transaction authorization and message signing
89
90
  - **Encryption Key**: ECIES encryption for private data exchange
90
91
  - **Derivation Path**: Hierarchical key generation for sub-identities
91
92
 
93
+ ### Key Derivation Hierarchy
94
+
95
+ BAP uses a two-level key derivation for signing operations:
96
+
97
+ ```
98
+ Root Key (HD or Type42 master)
99
+ ↓ path derivation
100
+ Member Key (identity root at path)
101
+ ↓ deriveChild(publicKey, "1-bap-identity")
102
+ Signing Key (used for on-chain operations)
103
+ ```
104
+
105
+ This structure ensures compatibility with BRC-100 wallet tooling while maintaining BAP's identity management features. The member key serves as the BRC-100 identity root, and the signing key is deterministically derived for on-chain operations.
106
+
92
107
  ## Implementation
93
108
 
94
109
  ### Installation
@@ -141,6 +156,25 @@ async function discoverIdentities(bap, checkExistsOnChain) {
141
156
  }
142
157
  ```
143
158
 
159
+ ### Migration from Legacy Derivation
160
+
161
+ Existing identities using the previous (pre-signing-key-derivation) format can be migrated:
162
+
163
+ ```javascript
164
+ // Check if identity needs migration
165
+ if (identity.needsRotation(registeredOnChainAddress)) {
166
+ // Get the rotation transaction OP_RETURN
167
+ const opReturn = identity.getLegacyRotationTransaction();
168
+
169
+ // App handles funding and broadcasting the transaction
170
+ // This rotates from legacy address to new derived signing address
171
+ }
172
+
173
+ // Utility methods for migration
174
+ const legacyAddress = identity.getLegacyAddress(); // Pre-derivation address
175
+ const newAddress = identity.getCurrentAddress(); // New derived address
176
+ ```
177
+
144
178
  ### Deprecation Notice
145
179
 
146
180
  The BIP32 initialization format using extended private keys (xprv) is deprecated. For new implementations, use Type 42 initialization with `{ rootPk: wifKey }`. The legacy BIP32 format remains supported for backward compatibility but should not be used in new projects.
@@ -20,6 +20,17 @@ declare abstract class BaseClass {
20
20
  privKey: PrivateKey;
21
21
  pubKey: PublicKey;
22
22
  };
23
+ /**
24
+ * Low-level BSM signing helper - signs a message with the given private key
25
+ * This consolidates the BSM signing logic used across all signing methods
26
+ * @param message - The message to sign as number array
27
+ * @param signingKey - The private key to sign with
28
+ * @returns Object containing address and base64 signature
29
+ */
30
+ protected signWithBSM(message: number[], signingKey: PrivateKey): {
31
+ address: string;
32
+ signature: string;
33
+ };
23
34
  /**
24
35
  * Encrypt the given string data with the identity encryption key
25
36
  * @param stringData
@@ -102,8 +102,42 @@ declare class MasterID extends BaseClass {
102
102
  * @returns {[]}
103
103
  */
104
104
  getIdTransaction(previousPath?: string): number[][];
105
+ /**
106
+ * Get the private key for a given path (before identity signing key derivation)
107
+ * This is the "member key" for the path
108
+ */
109
+ private getPathDerivedKey;
110
+ /**
111
+ * Get the identity signing key for a given path
112
+ * This is derived from the path key using the BAP protocol pattern
113
+ */
114
+ private getIdentitySigningKeyForPath;
115
+ /**
116
+ * Get the member key's public key for the given path
117
+ * This is the root key before signing key derivation
118
+ */
119
+ getMemberKey(path?: string): string;
120
+ /**
121
+ * Get the legacy (pre-signing-key-derivation) address for a path
122
+ * This is the address without the extra "1-bap-identity" derivation
123
+ */
124
+ getLegacyAddress(path?: string): string;
125
+ /**
126
+ * Check if the on-chain signing address uses legacy derivation
127
+ * @param registeredAddress The address registered on-chain (optional, defaults to rootAddress)
128
+ * @returns true if the registered address matches legacy derivation
129
+ */
130
+ needsRotation(registeredAddress?: string): boolean;
131
+ /**
132
+ * Get OP_RETURN for migrating from legacy to new signing address derivation
133
+ * Signs with the LEGACY key to prove ownership of the old address
134
+ * Caller handles funding and broadcast
135
+ * @returns OP_RETURN data as number[][]
136
+ */
137
+ getLegacyRotationTransaction(): number[][];
105
138
  /**
106
139
  * Get address for given path
140
+ * Returns the identity signing address (derived from member key)
107
141
  *
108
142
  * @param path
109
143
  * @returns {*}
@@ -182,6 +216,7 @@ declare class MasterID extends BaseClass {
182
216
  getAttestationHash(attribute: string): string | null;
183
217
  /**
184
218
  * Sign a message with the current signing address of this identity
219
+ * Uses the derived identity signing key
185
220
  *
186
221
  * @param message
187
222
  * @param signingPath
@@ -199,6 +234,7 @@ declare class MasterID extends BaseClass {
199
234
  * are rotated for this ID.
200
235
  *
201
236
  * This is used in for instance deterministic login systems, that do not support BAP.
237
+ * The signing address is derived from the seed-derived key.
202
238
  *
203
239
  * @param message
204
240
  * @param seed {string} String seed that will be used to generate a path
@@ -1,4 +1,4 @@
1
- import { type PublicKey, PrivateKey } from "@bsv/sdk";
1
+ import { PublicKey, PrivateKey } from "@bsv/sdk";
2
2
  import { BaseClass } from "./BaseClass";
3
3
  import type { IdentityAttributes, MemberIdentity } from "./interface";
4
4
  export declare class MemberID extends BaseClass {
@@ -8,6 +8,23 @@ export declare class MemberID extends BaseClass {
8
8
  address: string;
9
9
  identityKey: string;
10
10
  constructor(key: PrivateKey, identityAttributes?: IdentityAttributes);
11
+ /**
12
+ * Get the derived identity signing key
13
+ * This is derived from the member key using the BAP protocol pattern
14
+ * invoiceNumber = "1-bap-identity" (securityLevel-protocolName-keyID)
15
+ */
16
+ private getIdentitySigningKey;
17
+ /**
18
+ * Get the member key's public key
19
+ * This is the root key for this member before signing key derivation
20
+ * @returns The member's public key hex string
21
+ */
22
+ getMemberKey(): string;
23
+ /**
24
+ * Get the legacy (pre-signing-key-derivation) address
25
+ * This is the address without the extra "1-bap-identity" derivation
26
+ */
27
+ getLegacyAddress(): string;
11
28
  signMessage(message: number[], _signingPath?: string): {
12
29
  address: string;
13
30
  signature: string;
@@ -33,6 +50,43 @@ export declare class MemberID extends BaseClass {
33
50
  * Get the public key for encrypting data for this identity
34
51
  */
35
52
  getEncryptionPublicKey(): string;
53
+ /**
54
+ * Get a derived encryption key using a seed string (Type42 derivation)
55
+ * This allows deriving unique encryption keys per friend/conversation
56
+ * @param seed - The seed string (e.g., friend's BAP ID)
57
+ * @returns The derived private key for this seed
58
+ */
59
+ private getEncryptionPrivateKeyWithSeed;
60
+ /**
61
+ * Get the encryption key pair for a specific seed
62
+ * @param seed - The seed string (e.g., friend's BAP ID)
63
+ */
64
+ getEncryptionKeyWithSeed(seed: string): {
65
+ privKey: PrivateKey;
66
+ pubKey: PublicKey;
67
+ };
68
+ /**
69
+ * Get the public key for encrypting data for a specific seed
70
+ * This is the public key to include in friend requests
71
+ * @param seed - The seed string (e.g., friend's BAP ID)
72
+ */
73
+ getEncryptionPublicKeyWithSeed(seed: string): string;
74
+ /**
75
+ * Encrypt data using a seed-derived key
76
+ * @param stringData - The data to encrypt
77
+ * @param seed - The seed string for key derivation (e.g., friend's BAP ID)
78
+ * @param counterPartyPublicKey - Optional public key of the recipient
79
+ * @returns Base64 encoded encrypted data
80
+ */
81
+ encryptWithSeed(stringData: string, seed: string, counterPartyPublicKey?: string): string;
82
+ /**
83
+ * Decrypt data using a seed-derived key
84
+ * @param ciphertext - Base64 encoded encrypted data
85
+ * @param seed - The seed string for key derivation (e.g., friend's BAP ID)
86
+ * @param counterPartyPublicKey - Optional public key of the sender
87
+ * @returns Decrypted string
88
+ */
89
+ decryptWithSeed(ciphertext: string, seed: string, counterPartyPublicKey?: string): string;
36
90
  /**
37
91
  * Export member data in bitcoin-backup compatible format
38
92
  * @param label Optional user-defined label
@@ -6,3 +6,6 @@ export declare const BAP_SERVER = "https://api.sigmaidentity.com/v1";
6
6
  export declare const MAX_INT: number;
7
7
  export declare const SIGNING_PATH_PREFIX = "m/424150'/0'/0'";
8
8
  export declare const ENCRYPTION_PATH = "m/424150'/2147483647'/2147483647'";
9
+ export declare const BAP_PROTOCOL_ID: [1, string];
10
+ export declare const BAP_KEY_ID = "identity";
11
+ export declare const BAP_INVOICE_NUMBER = "1-bap-identity";
@@ -1,8 +1,8 @@
1
1
  // @bun
2
- import{BSM as l,BigNumber as wj,ECIES as Yj,HD as Gj,OP as K,Signature as Xj,PrivateKey as Fj}from"@bsv/sdk";import{Utils as Cj}from"@bsv/sdk";var i=async(j,$,J,q)=>{let z=`${J}${j}`;return(await fetch(z,{method:"post",headers:{"Content-type":"application/json; charset=utf-8",token:q,format:"json"},body:JSON.stringify($)})).json()},T=(j,$)=>async(J,q)=>{return i(J,q,j,$)};import{Utils as r}from"@bsv/sdk";var{toHex:b,toArray:m}=r,C="1BAPSuaPnfGnSBM3GLV9yhxUdYe4vGbdMT",p=b(m(C)),R="15PciHG22SNLQJXMoSUaWVi7WSqc7hCfva",Oj=b(m(R)),S="https://api.sigmaidentity.com/v1",F=2147483647,k="m/424150'/0'/0'",Y=`m/424150'/${F}'/${F}'`;import{BSM as E,Utils as Qj,ECIES as Zj,Hash as U,PublicKey as H,BigNumber as o,HD as Wj}from"@bsv/sdk";var G={getRandomBytes(j=32){if(typeof globalThis!=="undefined"&&globalThis.crypto&&globalThis.crypto.getRandomValues){let $=new Uint8Array(j);return globalThis.crypto.getRandomValues($),$}throw new Error("Secure random number generation not available. crypto.getRandomValues() is required for cryptographic operations. This environment may not be suitable for secure key generation.")},getRandomString(j=32){let $=this.getRandomBytes(j);return Array.from($,(J)=>J.toString(16).padStart(2,"0")).join("")},getSigningPathFromHex(j,$=!0){let J="m",q=j.match(/.{1,8}/g);if(!q)throw new Error("Invalid hex string");let z=2147483647;for(let Q of q){let W=Number(`0x${Q}`);if(W>z)W-=z;J+=`/${W}${$?"'":""}`}return J},getNextIdentityPath(j){let $=j.split("/"),J=$[$.length-2],q=!1;if(J.match("'"))q=!0;let z=(Number(J.replace(/[^0-9]/g,""))+1).toString();return $[$.length-2]=z+(q?"'":""),$[$.length-1]=`0${q?"'":""}`,$.join("/")},getNextPath(j){let $=j.split("/"),J=$[$.length-1],q=!1;if(J.match("'"))q=!0;let z=(Number(J.replace(/[^0-9]/g,""))+1).toString();return $[$.length-1]=z+(q?"'":""),$.join("/")}};import{BSM as g,PrivateKey as I,BigNumber as qj}from"@bsv/sdk";import{ECIES as a,Utils as e,OP as h,PublicKey as P}from"@bsv/sdk";var{toArray:M,toUTF8:t,toBase64:jj}=e,{electrumDecrypt:$j,electrumEncrypt:Jj}=a;class x{identityAttributes={};encrypt(j,$){let{privKey:J,pubKey:q}=this.getEncryptionKey(),z=$?P.fromString($):q;return jj(Jj(M(j),z,J))}decrypt(j,$){let{privKey:J}=this.getEncryptionKey(),q;if($)q=P.fromString($);return t($j(M(j,"base64"),J,q))}signOpReturnWithAIP(j,$){let J=this.getAIPMessageBuffer(j),{address:q,signature:z}=this.signMessage(J.flat(),$);return this.formatAIPOutput(J,q,z)}getAttributes(){return this.identityAttributes}getAttribute(j){if(this.identityAttributes[j])return this.identityAttributes[j];return null}setAttribute(j,$){if(!$)return;if(this.identityAttributes[j])this.updateExistingAttribute(j,$);else this.createNewAttribute(j,$)}unsetAttribute(j){delete this.identityAttributes[j]}addAttribute(j,$,J=""){let q=J;if(!J)q=G.getRandomString();this.identityAttributes[j]={value:$,nonce:q}}getAttributeUrns(){let j="";for(let $ in this.identityAttributes){let J=this.getAttributeUrn($);if(J)j+=`${J}
2
+ import{BSM as g,BigNumber as Uj,ECIES as Mj,HD as kj,OP as A,Signature as Vj,PrivateKey as Oj}from"@bsv/sdk";import{Utils as xj}from"@bsv/sdk";var y=async(j,$,J,q)=>{let z=`${J}${j}`;return(await fetch(z,{method:"post",headers:{"Content-type":"application/json; charset=utf-8",token:q,format:"json"},body:JSON.stringify($)})).json()},E=(j,$)=>async(J,q)=>{return y(J,q,j,$)};import{Utils as s}from"@bsv/sdk";var{toHex:m,toArray:c}=s,f="1BAPSuaPnfGnSBM3GLV9yhxUdYe4vGbdMT",b=m(c(f)),_="15PciHG22SNLQJXMoSUaWVi7WSqc7hCfva",Ej=m(c(_)),H="https://api.sigmaidentity.com/v1",F=2147483647,V="m/424150'/0'/0'",Y=`m/424150'/${F}'/${F}'`;var R="1-bap-identity";import{Utils as Xj,ECIES as Fj,Hash as C,PublicKey as N,HD as fj}from"@bsv/sdk";var X={getRandomBytes(j=32){if(typeof globalThis<"u"&&globalThis.crypto&&globalThis.crypto.getRandomValues){let $=new Uint8Array(j);return globalThis.crypto.getRandomValues($),$}throw Error("Secure random number generation not available. crypto.getRandomValues() is required for cryptographic operations. This environment may not be suitable for secure key generation.")},getRandomString(j=32){let $=this.getRandomBytes(j);return Array.from($,(J)=>J.toString(16).padStart(2,"0")).join("")},getSigningPathFromHex(j,$=!0){let J="m",q=j.match(/.{1,8}/g);if(!q)throw Error("Invalid hex string");let z=2147483647;for(let Q of q){let W=Number(`0x${Q}`);if(W>z)W-=z;J+=`/${W}${$?"'":""}`}return J},getNextIdentityPath(j){let $=j.split("/"),J=$[$.length-2],q=!1;if(J.match("'"))q=!0;let z=(Number(J.replace(/[^0-9]/g,""))+1).toString();return $[$.length-2]=z+(q?"'":""),$[$.length-1]=`0${q?"'":""}`,$.join("/")},getNextPath(j){let $=j.split("/"),J=$[$.length-1],q=!1;if(J.match("'"))q=!0;let z=(Number(J.replace(/[^0-9]/g,""))+1).toString();return $[$.length-1]=z+(q?"'":""),$.join("/")}};import{PublicKey as qj,PrivateKey as D,Hash as zj,Utils as Qj,ECIES as Zj}from"@bsv/sdk";import{ECIES as i,Utils as r,OP as p,PublicKey as h,BSM as S,BigNumber as a}from"@bsv/sdk";var{toArray:M,toUTF8:e,toBase64:t}=r,{magicHash:jj}=S,{electrumDecrypt:$j,electrumEncrypt:Jj}=i;class B{identityAttributes={};signWithBSM(j,$){let J=$.toPublicKey().toAddress(),q=S.sign(j,$,"raw"),z=new a(jj(j)),Q=q.CalculateRecoveryFactor($.toPublicKey(),z),W=S.sign(j,$,"raw").toCompact(Q,!0,"base64");return{address:J,signature:W}}encrypt(j,$){let{privKey:J,pubKey:q}=this.getEncryptionKey(),z=$?h.fromString($):q;return t(Jj(M(j),z,J))}decrypt(j,$){let{privKey:J}=this.getEncryptionKey(),q;if($)q=h.fromString($);return e($j(M(j,"base64"),J,q))}signOpReturnWithAIP(j,$){let J=this.getAIPMessageBuffer(j),{address:q,signature:z}=this.signMessage(J.flat(),$);return this.formatAIPOutput(J,q,z)}getAttributes(){return this.identityAttributes}getAttribute(j){if(this.identityAttributes[j])return this.identityAttributes[j];return null}setAttribute(j,$){if(!$)return;if(this.identityAttributes[j])this.updateExistingAttribute(j,$);else this.createNewAttribute(j,$)}unsetAttribute(j){delete this.identityAttributes[j]}addAttribute(j,$,J=""){let q=J;if(!J)q=X.getRandomString();this.identityAttributes[j]={value:$,nonce:q}}getAttributeUrns(){let j="";for(let $ in this.identityAttributes){let J=this.getAttributeUrn($);if(J)j+=`${J}
3
3
  `}return j}getAttributeUrn(j){let $=this.identityAttributes[j];if($)return`urn:bap:id:${j}:${$.value}:${$.nonce}`;return null}parseStringUrns(j){let $={},J=j.replace(/^\s+/g,"").replace(/\r/gm,"").split(`
4
- `);for(let q of J){let Q=q.replace(/^\s+/g,"").replace(/\s+$/g,"").split(":");if(Q[0]==="urn"&&Q[1]==="bap"&&Q[2]==="id"&&Q[3]&&Q[4]&&Q[5])$[Q[3]]={value:Q[4],nonce:Q[5]}}return $}parseAttributes(j){if(typeof j==="string")return this.parseStringUrns(j);for(let $ in j)if(!j[$].value||!j[$].nonce)throw new Error("Invalid identity attribute");return j||{}}updateExistingAttribute(j,$){if(typeof $==="string"){this.identityAttributes[j].value=$;return}if(this.identityAttributes[j].value=$.value||"",$.nonce)this.identityAttributes[j].nonce=$.nonce}createNewAttribute(j,$){if(typeof $==="string"){this.addAttribute(j,$);return}this.addAttribute(j,$.value||"",$.nonce)}getAIPMessageBuffer(j,$){let J=j.findIndex((z)=>z[0]===h.OP_RETURN),q=[];if(J===-1)q.push([h.OP_RETURN]),J=0;if($)for(let z of $)q.push(j[J+z]);else for(let z of j)q.push(z);return q}formatAIPOutput(j,$,J){let q=[M("|"),M(R),M("BITCOIN_ECDSA"),M($),M(J,"base64")];return[...j,...q]}}var{magicHash:zj}=g;class O extends x{key;idName;description;address;identityKey;constructor(j,$={}){super();this.key=j,this.address=j.toAddress(),this.idName="Member ID 1",this.description="",this.identityKey="",this.identityAttributes=this.parseAttributes($)}signMessage(j,$){let J=this.key,q=J.toAddress(),z=g.sign(j,J,"raw"),Q=new qj(zj(j)),W=z.CalculateRecoveryFactor(J.toPublicKey(),Q),L=g.sign(j,J,"raw").toCompact(W,!0,"base64");return{address:q,signature:L}}signOpReturnWithAIP(j){let $=this.getAIPMessageBuffer(j),{address:J,signature:q}=this.signMessage($.flat());return this.formatAIPOutput($,J,q)}getPublicKey(){return this.key.toPublicKey().toString()}import(j){this.idName=j.name,this.description=j.description,this.key=I.fromWif(j.derivedPrivateKey),this.address=this.key.toAddress(),this.identityAttributes=j.identityAttributes||{},this.identityKey=j.identityKey}static fromMemberIdentity(j){let $=new O(I.fromWif(j.derivedPrivateKey));return $.import(j),$}static fromBackup(j){let $=new O(I.fromWif(j.wif)),J=JSON.parse($.decrypt(j.id));return $.import(J),$}export(){return{name:this.idName,description:this.description,derivedPrivateKey:this.key.toWif(),address:this.address,identityAttributes:this.getAttributes(),identityKey:this.identityKey}}getEncryptionKey(){return{privKey:this.key.deriveChild(this.key.toPublicKey(),Y),pubKey:this.key.deriveChild(this.key.toPublicKey(),Y).toPublicKey()}}getEncryptionPublicKey(){let{pubKey:j}=this.getEncryptionKey();return j.toString()}exportForBackup(j){let $=this.export(),J=this.encrypt(JSON.stringify($));return{wif:this.key.toWif(),id:J,...j&&{label:j},createdAt:new Date().toISOString()}}}var{toArray:X,toHex:V,toBase58:Lj,toUTF8:n,toBase64:v}=Qj,{electrumDecrypt:u,electrumEncrypt:A}=Zj,{magicHash:d}=E;class f extends x{#$;#j;#J;#Q=S;#W="";#q;#Z;#z;#L;idName;description;rootAddress;identityKey;identityAttributes;getApiData;constructor(j,$={},J=""){super();if(j instanceof Wj)if(this.#J=!1,J){let z=V(U.sha256(J,"utf8")),Q=G.getSigningPathFromHex(z);this.#$=j.derive(Q)}else this.#$=j;else if(this.#J=!0,this.#j=j.rootPk,J){let z=V(U.sha256(J,"utf8"));this.#j=this.#j.deriveChild(this.#j.toPublicKey(),z)}if(this.#L=J,this.idName="ID 1",this.description="",this.#q=`${k}/0/0/0`,this.#Z=`${k}/0/0/0`,this.#z=`${k}/0/0/1`,this.#J){if(!this.#j)throw new Error("Master private key not initialized");let z=this.#j.deriveChild(this.#j.toPublicKey(),this.#q);this.rootAddress=z.toPublicKey().toAddress()}else{if(!this.#$)throw new Error("HD private key not initialized");let z=this.#$.derive(this.#q);this.rootAddress=z.privKey.toPublicKey().toAddress()}this.identityKey=this.deriveIdentityKey(this.rootAddress);let q={...$};this.identityAttributes=this.parseAttributes(q),this.getApiData=T(this.#Q,this.#W)}set BAP_SERVER(j){this.#Q=j}get BAP_SERVER(){return this.#Q}set BAP_TOKEN(j){this.#W=j}get BAP_TOKEN(){return this.#W}deriveIdentityKey(j){let $=V(U.sha256(j,"utf8"));return Lj(U.ripemd160($,"hex"))}parseAttributes(j){if(typeof j==="string")return this.parseStringUrns(j);for(let $ in j)if(!j[$].value||!j[$].nonce)throw new Error("Invalid identity attribute");return j||{}}parseStringUrns(j){let $={},J=j.replace(/^\s+/g,"").replace(/\r/gm,"").split(`
5
- `);for(let q of J){let Q=q.replace(/^\s+/g,"").replace(/\s+$/g,"").split(":");if(Q[0]==="urn"&&Q[1]==="bap"&&Q[2]==="id"&&Q[3]&&Q[4]&&Q[5])$[Q[3]]={value:Q[4],nonce:Q[5]}}return $}getIdentityKey(){return this.identityKey}set rootPath(j){if(this.#J){if(this.#q=j,!this.#j)throw new Error("Master private key not initialized");let $=this.#j.deriveChild(this.#j.toPublicKey(),j);this.rootAddress=$.toPublicKey().toAddress(),this.#Z=j,this.#z=j}else{let $=j;if(j.split("/").length<5)$=`${k}${j}`;if(!this.validatePath($))throw new Error(`invalid signing path given ${$}`);if(this.#q=$,!this.#$)throw new Error("HD private key not initialized");let J=this.#$.derive($);this.rootAddress=J.pubKey.toAddress(),this.#Z=$,this.#z=$}this.identityKey=this.deriveIdentityKey(this.rootAddress)}get rootPath(){return this.#q}getRootPath(){return this.#q}set currentPath(j){if(this.#J)this.#Z=this.#z,this.#z=j;else{let $=j;if(j.split("/").length<5)$=`${k}${j}`;if(!this.validatePath($))throw new Error("invalid signing path given");this.#Z=this.#z,this.#z=$}}get currentPath(){return this.#z}get previousPath(){return this.#Z}get idSeed(){return this.#L}incrementPath(){this.currentPath=G.getNextPath(this.currentPath)}validatePath(j){if(j.match(/\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?/)){let $=j.split("/");if($.length===7&&Number($[1].replace("'",""))<=F&&Number($[2].replace("'",""))<=F&&Number($[3].replace("'",""))<=F&&Number($[4].replace("'",""))<=F&&Number($[5].replace("'",""))<=F&&Number($[6].replace("'",""))<=F)return!0}return!1}getInitialIdTransaction(){return this.getIdTransaction(this.#q)}getIdTransaction(j=""){if(this.#z===this.#q)throw new Error("Current path equals rootPath. ID was probably not initialized properly");let $=[X(C),X("ID"),X(this.identityKey),X(this.getCurrentAddress())];return this.signOpReturnWithAIP($,j||this.#Z)}getAddress(j){if(this.#J){if(!this.#j)throw new Error("Master private key not initialized");return this.#j.deriveChild(this.#j.toPublicKey(),j).toPublicKey().toAddress()}if(!this.#$)throw new Error("HD private key not initialized");return this.#$.derive(j).privKey.toPublicKey().toAddress()}getCurrentAddress(){return this.getAddress(this.#z)}getEncryptionKey(){if(this.#J){if(!this.#j)throw new Error("Master private key not initialized");let J=this.#j.deriveChild(this.#j.toPublicKey(),this.#q),q=J.deriveChild(J.toPublicKey(),Y);return{privKey:q,pubKey:q.toPublicKey()}}if(!this.#$)throw new Error("HD private key not initialized");let $=this.#$.derive(this.#q).derive(Y).privKey;return{privKey:$,pubKey:$.toPublicKey()}}getEncryptionKeyType42(){if(this.#J)return this.getEncryptionKey();if(!this.#$)throw new Error("HD private key not initialized");let j=this.#$.derive(this.#q),$=j.privKey.deriveChild(j.toPublic().pubKey,Y);return{privKey:$,pubKey:$.toPublicKey()}}getEncryptionPublicKey(){let{pubKey:j}=this.getEncryptionKey();return j.toString()}getEncryptionPublicKeyWithSeed(j){return this.getEncryptionPrivateKeyWithSeed(j).toPublicKey().toString()}encrypt(j,$){let{privKey:J,pubKey:q}=this.getEncryptionKey(),z=$?H.fromString($):q;return v(A(X(j),z,J))}decrypt(j,$){let{privKey:J}=this.getEncryptionKey(),q;if($)q=H.fromString($);return n(u(X(j,"base64"),J,q))}encryptWithSeed(j,$,J){let q=this.getEncryptionPrivateKeyWithSeed($),z=q.toPublicKey(),Q=J?H.fromString(J):z;return v(A(X(j),Q,q))}decryptWithSeed(j,$,J){let q=this.getEncryptionPrivateKeyWithSeed($),z;if(J)z=H.fromString(J);return n(u(X(j,"base64"),q,z))}getEncryptionPrivateKeyWithSeed(j){let $=V(U.sha256(j,"utf8"));if(this.#J){if(!this.#j)throw new Error("Master private key not initialized");let z=this.#j.deriveChild(this.#j.toPublicKey(),this.#q);return z.deriveChild(z.toPublicKey(),$)}if(!this.#$)throw new Error("HD private key not initialized");let J=G.getSigningPathFromHex($);return this.#$.derive(this.#q).derive(J).privKey}getAttestation(j){let $=U.sha256(j,"utf8");return`bap:attest:${V($)}:${this.getIdentityKey()}`}getAttestationHash(j){let $=this.getAttributeUrn(j);if(!$)return null;let J=this.getAttestation($),q=U.sha256(J,"utf8");return V(q)}signMessage(j,$){let J=$||this.#z,q;if(this.#J){if(!this.#j)throw new Error("Master private key not initialized");q=this.#j.deriveChild(this.#j.toPublicKey(),J)}else{if(!this.#$)throw new Error("HD private key not initialized");q=this.#$.derive(J).privKey}let z=q.toAddress(),Q=E.sign(j,q,"raw"),W=new o(d(j)),L=Q.CalculateRecoveryFactor(q.toPublicKey(),W),w=E.sign(j,q,"raw").toCompact(L,!0,"base64");return{address:z,signature:w}}signMessageWithSeed(j,$){let J=V(U.sha256($,"utf8")),q;if(this.#J){if(!this.#j)throw new Error("Master private key not initialized");let N=this.#j.deriveChild(this.#j.toPublicKey(),this.#q);q=N.deriveChild(N.toPublicKey(),J)}else{if(!this.#$)throw new Error("HD private key not initialized");let N=G.getSigningPathFromHex(J);q=this.#$.derive(this.#q).derive(N).privKey}let z=q.toPublicKey().toAddress(),Q=X(j,"utf8"),W=E.sign(Q,q,"raw"),L=new o(d(Q)),w=W.CalculateRecoveryFactor(q.toPublicKey(),L),B=E.sign(Q,q,"raw").toCompact(w,!0,"base64");return{address:z,signature:B}}signOpReturnWithAIP(j,$=""){let J=this.getAIPMessageBuffer(j),{address:q,signature:z}=this.signMessage(J.flat(),$);return this.formatAIPOutput(j,q,z)}async getIdSigningKeys(){let j=await this.getApiData("/signing-keys",{idKey:this.identityKey});return console.log("getIdSigningKeys",j),j}async getAttributeAttestations(j){let $=this.getAttestationHash(j),J=await this.getApiData("/attestation/get",{hash:$});return console.log("getAttestations",j,$,J),J}import(j){this.idName=j.name,this.description=j.description||"",this.identityKey=j.identityKey,this.#q=j.rootPath,this.rootAddress=j.rootAddress,this.#Z=j.previousPath,this.#z=j.currentPath,this.#L=("idSeed"in j?j.idSeed:"")||"",this.identityAttributes=this.parseAttributes(j.identityAttributes)}export(){return{name:this.idName,description:this.description,identityKey:this.identityKey,rootPath:this.#q,rootAddress:this.rootAddress,previousPath:this.#Z,currentPath:this.#z,idSeed:this.#L,identityAttributes:this.getAttributes(),lastIdPath:""}}exportMemberBackup(){let j;if(this.#J){if(!this.#j)throw new Error("Master private key not initialized");j=this.#j.deriveChild(this.#j.toPublicKey(),this.#z)}else{if(!this.#$)throw new Error("HD private key not initialized");j=this.#$.derive(this.#z).privKey}return{name:this.idName,description:this.description,derivedPrivateKey:j.toWif(),address:j.toPublicKey().toAddress(),identityAttributes:this.getAttributes(),identityKey:this.identityKey}}newId(){this.incrementPath();let j;if(this.#J){if(!this.#j)throw new Error("Master private key not initialized");j=this.#j.deriveChild(this.#j.toPublicKey(),this.#z)}else{if(!this.#$)throw new Error("HD private key not initialized");j=this.#$.derive(this.#z).privKey}return new O(j)}exportMember(){let j=this.exportMemberBackup(),$;if(this.#J){if(!this.#j)throw new Error("Master private key not initialized");$=this.#j.deriveChild(this.#j.toPublicKey(),this.#z)}else{if(!this.#$)throw new Error("HD private key not initialized");$=this.#$.derive(this.#z).privKey}let J=v(A(X(JSON.stringify(j)),$.toPublicKey()));return{wif:j.derivedPrivateKey,encryptedData:J}}}var{toArray:Z,toUTF8:_,toBase64:c,toHex:D}=Cj,{electrumEncrypt:y,electrumDecrypt:s}=Yj;class Uj{#$;#j;#J;#Q={};#W=S;#q="";#Z="";#z=0;getApiData;constructor(j,$="",J=""){if(!j)throw new Error("No key source given");if(typeof j==="string")this.#$=Gj.fromString(j),this.#J=!1;else this.#j=Fj.fromWif(j.rootPk),this.#J=!0;if($)this.#q=$;if(J)this.#W=J;this.getApiData=T(this.#W,this.#q)}get lastIdPath(){return this.#Z}getPublicKey(j=""){if(this.#J){if(!this.#j)throw new Error("Master private key not initialized");if(j)return this.#j.deriveChild(this.#j.toPublicKey(),j).toPublicKey().toString();return this.#j.toPublicKey().toString()}if(!this.#$)throw new Error("HD private key not initialized");if(j)return this.#$.derive(j).pubKey.toString();return this.#$.pubKey.toString()}getHdPublicKey(j=""){if(this.#J)throw new Error("HD public keys are not available in Type 42 mode");if(!this.#$)throw new Error("HD private key not initialized");if(j)return this.#$.derive(j).toPublic().toString();return this.#$.toPublic().toString()}set BAP_SERVER(j){this.#W=j;for(let $ in this.#Q)this.#Q[$].BAP_SERVER=j}get BAP_SERVER(){return this.#W}set BAP_TOKEN(j){this.#q=j;for(let $ in this.#Q)this.#Q[$].BAP_TOKEN=j}get BAP_TOKEN(){return this.#q}checkIdBelongs(j){let $;if(this.#J){if(!this.#j)throw new Error("Master private key not initialized");$=this.#j.deriveChild(this.#j.toPublicKey(),j.rootPath).toPublicKey().toAddress()}else{if(!this.#$)throw new Error("HD private key not initialized");$=this.#$.derive(j.rootPath).pubKey.toAddress()}if($!==j.rootAddress)throw new Error("ID does not belong to this private key");return!0}listIds(){return Object.keys(this.#Q)}newId(j,$,J={},q=""){let z,Q,W;if(typeof j==="object"||j===void 0||typeof j==="string"&&j.startsWith("/"))Q=typeof j==="string"?j:void 0,W=typeof j==="object"?j:typeof $==="object"?$:{},z="Default Identity";else z=j,Q=typeof $==="string"?$:void 0,W=typeof $==="object"?$:J;let L;if(Q)L=Q;else if(this.#J)L=`bap:${this.#z}`,this.#z++;else L=this.getNextValidPath();let w;if(this.#J){if(!this.#j)throw new Error("Type 42 parameters not initialized");w=new f({rootPk:this.#j},W,q)}else{if(!this.#$)throw new Error("HD private key not initialized");w=new f(this.#$,W,q)}if(w.BAP_SERVER=this.#W,w.BAP_TOKEN=this.#q,w.idName=z,w.rootPath=L,this.#J)w.currentPath=L;else w.currentPath=G.getNextPath(L);let B=w.getIdentityKey();return this.#Q[B]=w,this.#Z=L,this.#Q[B]}removeId(j){delete this.#Q[j]}getNextValidPath(){if(this.#Z)return G.getNextIdentityPath(this.#Z);return`/0'/${Object.keys(this.#Q).length}'/0'`}newIdWithCounter(j,$=`Identity ${j}`){if(!this.#J)throw new Error("newIdWithCounter only works in Type 42 mode");let J=`bap:${j}`;return this.newId($,J)}getId(j){return this.#Q[j]||null}setId(j){this.checkIdBelongs(j),this.#Q[j.getIdentityKey()]=j}importIds(j,$=!0){if($&&typeof j==="string"){this.importEncryptedIds(j);return}let J=j;if(!J.lastIdPath)throw new Error("ID cannot be imported as it is not complete");if(!J.ids)throw new Error(`ID data is not in the correct format: ${j}`);let q=j.lastIdPath;for(let z of J.ids){if(!z.identityKey||!z.identityAttributes||!z.rootAddress)throw new Error("ID cannot be imported as it is not complete");let Q;if(this.#J){if(!this.#j)throw new Error("Type 42 parameters not initialized");Q=new f({rootPk:this.#j},{},z.idSeed)}else{if(!this.#$)throw new Error("HD private key not initialized");Q=new f(this.#$,{},z.idSeed)}if(Q.BAP_SERVER=this.#W,Q.BAP_TOKEN=this.#q,Q.import(z),q==="")q=Q.currentPath;if(this.checkIdBelongs(Q),this.#Q[Q.getIdentityKey()]=Q,this.#J&&Q.rootPath.startsWith("bap:")){let W=Q.rootPath.split(":");if(W.length>=2){let L=Number.parseInt(W[1],10);if(!Number.isNaN(L))this.#z=Math.max(this.#z,L+1)}}}this.#Z=q}importEncryptedIds(j){let $=this.decrypt(j),J=JSON.parse($);if(Array.isArray(J)){console.log(`Importing old format:
6
- `,J),this.importOldIds(J);return}if(typeof J!=="object")throw new Error("decrypted, but found unrecognized identities format");this.importIds(J,!1)}importOldIds(j){for(let $ of j){let J;if(this.#J){if(!this.#j)throw new Error("Type 42 parameters not initialized");J=new f({rootPk:this.#j},{},$.idSeed??"")}else{if(!this.#$)throw new Error("HD private key not initialized");J=new f(this.#$,{},$.idSeed??"")}J.BAP_SERVER=this.#W,J.BAP_TOKEN=this.#q,J.import($),this.checkIdBelongs(J),this.#Q[J.getIdentityKey()]=J,this.#Z=J.currentPath}}exportIds(j,$=!0){let J={lastIdPath:this.#Z,ids:[]},q=j||Object.keys(this.#Q);for(let z of q){if(!this.#Q[z])throw new Error(`Identity ${z} not found`);J.ids.push(this.#Q[z].export())}if($)return this.encrypt(JSON.stringify(J));return J}exportId(j,$=!0){let J={lastIdPath:this.#Z,ids:[]};if(J.ids.push(this.#Q[j].export()),$)return this.encrypt(JSON.stringify(J));return J}encrypt(j){if(this.#J){if(!this.#j)throw new Error("Master private key not initialized");let J=this.#j.deriveChild(this.#j.toPublicKey(),Y);return c(y(Z(j),J.toPublicKey(),null))}if(!this.#$)throw new Error("HD private key not initialized");let $=this.#$.derive(Y);return c(y(Z(j),$.pubKey,null))}decrypt(j){if(this.#J){if(!this.#j)throw new Error("Master private key not initialized");let J=this.#j.deriveChild(this.#j.toPublicKey(),Y);return _(s(Z(j,"base64"),J))}if(!this.#$)throw new Error("HD private key not initialized");let $=this.#$.derive(Y);return _(s(Z(j,"base64"),$.privKey))}signAttestationWithAIP(j,$,J=0,q=""){let z=this.getId($);if(!z)throw new Error("Could not find identity to attest with");let Q=this.getAttestationBuffer(j,J,q),{address:W,signature:L}=z.signMessage(Q);return this.createAttestationTransaction(j,J,W,L,q)}verifyAttestationWithAIP(j){if(!j.every((q)=>Array.isArray(q))||j[0][0]!==K.OP_RETURN||D(j[1])!==p)throw new Error("Not a valid BAP transaction");let $=D(j[7])==="44415441"?5:0,J={type:_(j[2]),hash:D(j[3]),sequence:_(j[4]),signingProtocol:_(j[7+$]),signingAddress:_(j[8+$]),signature:c(j[9+$])};if($&&j[3]===j[8])J.data=D(j[9]);console.log({attestation:J});try{let q=[];for(let z=0;z<6+$;z++)q.push(j[z]);J.verified=this.verifySignature(q.flat(),J.signingAddress,J.signature)}catch{J.verified=!1}return J}createAttestationTransaction(j,$,J,q,z=""){let Q=[[K.OP_RETURN],Z(C),Z("ATTEST"),Z(j),Z(`${$}`),Z("|")];if(z)Q.push(Z(C),Z("DATA"),Z(j),Z(z),Z("|"));return Q.push(Z(R),Z("BITCOIN_ECDSA"),Z(J),Z(q,"base64")),console.log({elements:Q}),Q}getAttestationBuffer(j,$=0,J=""){let q=[[K.OP_RETURN],Z(C),Z("ATTEST"),Z(j),Z(`${$}`),Z("|")];if(J)q.push(Z(C),Z("DATA"),Z(j),Z(J),Z("|"));return q.flat()}verifySignature(j,$,J){let q;if(Array.isArray(j))q=j;else if(Buffer.isBuffer(j))q=[...j];else q=Z(j,"utf8");let z=Xj.fromCompact(J,"base64"),Q;for(let W=0;W<4;W++)try{if(Q=z.RecoverPublicKey(W,new wj(l.magicHash(q))),l.verify(q,z,Q)&&Q.toAddress()===$)return!0}catch{}return!1}async verifyChallengeSignature(j,$,J,q){if(!this.verifySignature(J,$,q))return!1;try{let Q=await this.getApiData("/attestation/valid",{idKey:j,address:$,challenge:J,signature:q});if(Q?.status==="success"&&Q?.result?.valid===!0)return!0;return!1}catch(Q){return console.error("API call failed:",Q),!1}}async isValidAttestationTransaction(j){if(this.verifyAttestationWithAIP(j))return this.getApiData("/attestation/valid",{tx:j});return!1}async getIdentityFromAddress(j){return this.getApiData("/identity/from-address",{address:j})}async getIdentity(j){return this.getApiData("/identity/get",{idKey:j})}async getAttestationsForHash(j){return this.getApiData("/attestations",{hash:j})}exportForBackup(j,$,J){let z={ids:this.exportIds(),...j&&{label:j},createdAt:new Date().toISOString()};if(this.#J){if(!this.#j)throw new Error("Type 42 parameters not initialized");return{...z,rootPk:this.#j.toWif()}}if(!this.#$)throw new Error("HD private key not initialized");return{...z,xprv:$||this.#$.toString(),mnemonic:J||""}}exportMemberForBackup(j,$){let J=this.#Q[j];if(!J)throw new Error(`Identity ${j} not found`);let q=J.exportMember();return{wif:q.wif,id:q.encryptedData,...$&&{label:$},createdAt:new Date().toISOString()}}}export{O as MemberID,f as MasterID,Uj as BAP};
4
+ `);for(let q of J){let Q=q.replace(/^\s+/g,"").replace(/\s+$/g,"").split(":");if(Q[0]==="urn"&&Q[1]==="bap"&&Q[2]==="id"&&Q[3]&&Q[4]&&Q[5])$[Q[3]]={value:Q[4],nonce:Q[5]}}return $}parseAttributes(j){if(typeof j==="string")return this.parseStringUrns(j);for(let $ in j)if(!j[$].value||!j[$].nonce)throw Error("Invalid identity attribute");return j||{}}updateExistingAttribute(j,$){if(typeof $==="string"){this.identityAttributes[j].value=$;return}if(this.identityAttributes[j].value=$.value||"",$.nonce)this.identityAttributes[j].nonce=$.nonce}createNewAttribute(j,$){if(typeof $==="string"){this.addAttribute(j,$);return}this.addAttribute(j,$.value||"",$.nonce)}getAIPMessageBuffer(j,$){let J=j.findIndex((z)=>z[0]===p.OP_RETURN),q=[];if(J===-1)q.push([p.OP_RETURN]),J=0;if($)for(let z of $)q.push(j[J+z]);else for(let z of j)q.push(z);return q}formatAIPOutput(j,$,J){let q=[M("|"),M(_),M("BITCOIN_ECDSA"),M($),M(J,"base64")];return[...j,...q]}}var{toArray:P,toUTF8:Wj,toBase64:Lj,toHex:wj}=Qj,{electrumDecrypt:Yj,electrumEncrypt:Gj}=Zj;class O extends B{key;idName;description;address;identityKey;constructor(j,$={}){super();this.key=j,this.address=this.getIdentitySigningKey().toPublicKey().toAddress(),this.idName="Member ID 1",this.description="",this.identityKey="",this.identityAttributes=this.parseAttributes($)}getIdentitySigningKey(){return this.key.deriveChild(this.key.toPublicKey(),R)}getMemberKey(){return this.key.toPublicKey().toString()}getLegacyAddress(){return this.key.toPublicKey().toAddress()}signMessage(j,$){let J=this.getIdentitySigningKey();return this.signWithBSM(j,J)}signOpReturnWithAIP(j){let $=this.getAIPMessageBuffer(j),{address:J,signature:q}=this.signMessage($.flat());return this.formatAIPOutput($,J,q)}getPublicKey(){return this.getIdentitySigningKey().toPublicKey().toString()}import(j){this.idName=j.name,this.description=j.description,this.key=D.fromWif(j.derivedPrivateKey),this.address=this.getIdentitySigningKey().toPublicKey().toAddress(),this.identityAttributes=j.identityAttributes||{},this.identityKey=j.identityKey}static fromMemberIdentity(j){let $=new O(D.fromWif(j.derivedPrivateKey));return $.import(j),$}static fromBackup(j){let $=new O(D.fromWif(j.wif)),J=JSON.parse($.decrypt(j.id));return $.import(J),$}export(){return{name:this.idName,description:this.description,derivedPrivateKey:this.key.toWif(),address:this.address,identityAttributes:this.getAttributes(),identityKey:this.identityKey}}getEncryptionKey(){return{privKey:this.key.deriveChild(this.key.toPublicKey(),Y),pubKey:this.key.deriveChild(this.key.toPublicKey(),Y).toPublicKey()}}getEncryptionPublicKey(){let{pubKey:j}=this.getEncryptionKey();return j.toString()}getEncryptionPrivateKeyWithSeed(j){let $=wj(zj.sha256(j,"utf8"));return this.key.deriveChild(this.key.toPublicKey(),$)}getEncryptionKeyWithSeed(j){let $=this.getEncryptionPrivateKeyWithSeed(j);return{privKey:$,pubKey:$.toPublicKey()}}getEncryptionPublicKeyWithSeed(j){return this.getEncryptionPrivateKeyWithSeed(j).toPublicKey().toString()}encryptWithSeed(j,$,J){let q=this.getEncryptionPrivateKeyWithSeed($),z=q.toPublicKey(),Q=this.key.toPublicKey().constructor,W=J?Q.fromString(J):z;return Lj(Gj(P(j),W,q))}decryptWithSeed(j,$,J){let q=this.getEncryptionPrivateKeyWithSeed($),z;if(J)z=qj.fromString(J);return Wj(Yj(P(j,"base64"),q,z))}exportForBackup(j){let $=this.export(),J=this.encrypt(JSON.stringify($));return{wif:this.key.toWif(),id:J,...j&&{label:j},createdAt:new Date().toISOString()}}}var{toArray:w,toHex:k,toBase58:Cj,toUTF8:o,toBase64:I}=Xj,{electrumDecrypt:u,electrumEncrypt:v}=Fj;class U extends B{#$;#j;#q;#Q=H;#W="";#J;#Z;#z;#L;idName;description;rootAddress;identityKey;identityAttributes;getApiData;constructor(j,$={},J=""){super();if(j instanceof fj)if(this.#q=!1,J){let z=k(C.sha256(J,"utf8")),Q=X.getSigningPathFromHex(z);this.#$=j.derive(Q)}else this.#$=j;else if(this.#q=!0,this.#j=j.rootPk,J){let z=k(C.sha256(J,"utf8"));this.#j=this.#j.deriveChild(this.#j.toPublicKey(),z)}if(this.#L=J,this.idName="ID 1",this.description="",this.#J=`${V}/0/0/0`,this.#Z=`${V}/0/0/0`,this.#z=`${V}/0/0/1`,this.#q){if(!this.#j)throw Error("Master private key not initialized");let z=this.#j.deriveChild(this.#j.toPublicKey(),this.#J);this.rootAddress=z.toPublicKey().toAddress()}else{if(!this.#$)throw Error("HD private key not initialized");let z=this.#$.derive(this.#J);this.rootAddress=z.privKey.toPublicKey().toAddress()}this.identityKey=this.deriveIdentityKey(this.rootAddress);let q={...$};this.identityAttributes=this.parseAttributes(q),this.getApiData=E(this.#Q,this.#W)}set BAP_SERVER(j){this.#Q=j}get BAP_SERVER(){return this.#Q}set BAP_TOKEN(j){this.#W=j}get BAP_TOKEN(){return this.#W}deriveIdentityKey(j){let $=k(C.sha256(j,"utf8"));return Cj(C.ripemd160($,"hex"))}parseAttributes(j){if(typeof j==="string")return this.parseStringUrns(j);for(let $ in j)if(!j[$].value||!j[$].nonce)throw Error("Invalid identity attribute");return j||{}}parseStringUrns(j){let $={},J=j.replace(/^\s+/g,"").replace(/\r/gm,"").split(`
5
+ `);for(let q of J){let Q=q.replace(/^\s+/g,"").replace(/\s+$/g,"").split(":");if(Q[0]==="urn"&&Q[1]==="bap"&&Q[2]==="id"&&Q[3]&&Q[4]&&Q[5])$[Q[3]]={value:Q[4],nonce:Q[5]}}return $}getIdentityKey(){return this.identityKey}set rootPath(j){if(this.#q){if(this.#J=j,!this.#j)throw Error("Master private key not initialized");let $=this.#j.deriveChild(this.#j.toPublicKey(),j);this.rootAddress=$.toPublicKey().toAddress(),this.#Z=j,this.#z=j}else{let $=j;if(j.split("/").length<5)$=`${V}${j}`;if(!this.validatePath($))throw Error(`invalid signing path given ${$}`);if(this.#J=$,!this.#$)throw Error("HD private key not initialized");let J=this.#$.derive($);this.rootAddress=J.pubKey.toAddress(),this.#Z=$,this.#z=$}this.identityKey=this.deriveIdentityKey(this.rootAddress)}get rootPath(){return this.#J}getRootPath(){return this.#J}set currentPath(j){if(this.#q)this.#Z=this.#z,this.#z=j;else{let $=j;if(j.split("/").length<5)$=`${V}${j}`;if(!this.validatePath($))throw Error("invalid signing path given");this.#Z=this.#z,this.#z=$}}get currentPath(){return this.#z}get previousPath(){return this.#Z}get idSeed(){return this.#L}incrementPath(){this.currentPath=X.getNextPath(this.currentPath)}validatePath(j){if(j.match(/\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?/)){let $=j.split("/");if($.length===7&&Number($[1].replace("'",""))<=F&&Number($[2].replace("'",""))<=F&&Number($[3].replace("'",""))<=F&&Number($[4].replace("'",""))<=F&&Number($[5].replace("'",""))<=F&&Number($[6].replace("'",""))<=F)return!0}return!1}getInitialIdTransaction(){return this.getIdTransaction(this.#J)}getIdTransaction(j=""){if(this.#z===this.#J)throw Error("Current path equals rootPath. ID was probably not initialized properly");let $=[w(f),w("ID"),w(this.identityKey),w(this.getCurrentAddress())];return this.signOpReturnWithAIP($,j||this.#Z)}getPathDerivedKey(j){if(this.#q){if(!this.#j)throw Error("Master private key not initialized");return this.#j.deriveChild(this.#j.toPublicKey(),j)}if(!this.#$)throw Error("HD private key not initialized");return this.#$.derive(j).privKey}getIdentitySigningKeyForPath(j){let $=this.getPathDerivedKey(j);return $.deriveChild($.toPublicKey(),R)}getMemberKey(j){let $=j||this.#z;return this.getPathDerivedKey($).toPublicKey().toString()}getLegacyAddress(j){let $=j||this.#z;return this.getPathDerivedKey($).toPublicKey().toAddress()}needsRotation(j){let $=j||this.rootAddress,J=this.getLegacyAddress(this.#J);return $===J}getLegacyRotationTransaction(){let j=this.getAddress(this.#J),$=[w(f),w("ID"),w(this.identityKey),w(j)],J=this.getAIPMessageBuffer($),q=this.getPathDerivedKey(this.#J),{address:z,signature:Q}=this.signWithBSM(J.flat(),q);return this.formatAIPOutput($,z,Q)}getAddress(j){return this.getIdentitySigningKeyForPath(j).toPublicKey().toAddress()}getCurrentAddress(){return this.getAddress(this.#z)}getEncryptionKey(){if(this.#q){if(!this.#j)throw Error("Master private key not initialized");let J=this.#j.deriveChild(this.#j.toPublicKey(),this.#J),q=J.deriveChild(J.toPublicKey(),Y);return{privKey:q,pubKey:q.toPublicKey()}}if(!this.#$)throw Error("HD private key not initialized");let $=this.#$.derive(this.#J).derive(Y).privKey;return{privKey:$,pubKey:$.toPublicKey()}}getEncryptionKeyType42(){if(this.#q)return this.getEncryptionKey();if(!this.#$)throw Error("HD private key not initialized");let j=this.#$.derive(this.#J),$=j.privKey.deriveChild(j.toPublic().pubKey,Y);return{privKey:$,pubKey:$.toPublicKey()}}getEncryptionPublicKey(){let{pubKey:j}=this.getEncryptionKey();return j.toString()}getEncryptionPublicKeyWithSeed(j){return this.getEncryptionPrivateKeyWithSeed(j).toPublicKey().toString()}encrypt(j,$){let{privKey:J,pubKey:q}=this.getEncryptionKey(),z=$?N.fromString($):q;return I(v(w(j),z,J))}decrypt(j,$){let{privKey:J}=this.getEncryptionKey(),q;if($)q=N.fromString($);return o(u(w(j,"base64"),J,q))}encryptWithSeed(j,$,J){let q=this.getEncryptionPrivateKeyWithSeed($),z=q.toPublicKey(),Q=J?N.fromString(J):z;return I(v(w(j),Q,q))}decryptWithSeed(j,$,J){let q=this.getEncryptionPrivateKeyWithSeed($),z;if(J)z=N.fromString(J);return o(u(w(j,"base64"),q,z))}getEncryptionPrivateKeyWithSeed(j){let $=k(C.sha256(j,"utf8"));if(this.#q){if(!this.#j)throw Error("Master private key not initialized");let z=this.#j.deriveChild(this.#j.toPublicKey(),this.#J);return z.deriveChild(z.toPublicKey(),$)}if(!this.#$)throw Error("HD private key not initialized");let J=X.getSigningPathFromHex($);return this.#$.derive(this.#J).derive(J).privKey}getAttestation(j){let $=C.sha256(j,"utf8");return`bap:attest:${k($)}:${this.getIdentityKey()}`}getAttestationHash(j){let $=this.getAttributeUrn(j);if(!$)return null;let J=this.getAttestation($),q=C.sha256(J,"utf8");return k(q)}signMessage(j,$){let J=$||this.#z,q=this.getIdentitySigningKeyForPath(J);return this.signWithBSM(j,q)}signMessageWithSeed(j,$){let J=k(C.sha256($,"utf8")),q;if(this.#q){if(!this.#j)throw Error("Master private key not initialized");let Q=this.#j.deriveChild(this.#j.toPublicKey(),this.#J);q=Q.deriveChild(Q.toPublicKey(),J)}else{if(!this.#$)throw Error("HD private key not initialized");let Q=X.getSigningPathFromHex(J);q=this.#$.derive(this.#J).derive(Q).privKey}let z=q.deriveChild(q.toPublicKey(),R);return this.signWithBSM(w(j,"utf8"),z)}signOpReturnWithAIP(j,$=""){let J=this.getAIPMessageBuffer(j),{address:q,signature:z}=this.signMessage(J.flat(),$);return this.formatAIPOutput(j,q,z)}async getIdSigningKeys(){let j=await this.getApiData("/signing-keys",{idKey:this.identityKey});return console.log("getIdSigningKeys",j),j}async getAttributeAttestations(j){let $=this.getAttestationHash(j),J=await this.getApiData("/attestation/get",{hash:$});return console.log("getAttestations",j,$,J),J}import(j){this.idName=j.name,this.description=j.description||"",this.identityKey=j.identityKey,this.#J=j.rootPath,this.rootAddress=j.rootAddress,this.#Z=j.previousPath,this.#z=j.currentPath,this.#L=("idSeed"in j?j.idSeed:"")||"",this.identityAttributes=this.parseAttributes(j.identityAttributes)}export(){return{name:this.idName,description:this.description,identityKey:this.identityKey,rootPath:this.#J,rootAddress:this.rootAddress,previousPath:this.#Z,currentPath:this.#z,idSeed:this.#L,identityAttributes:this.getAttributes(),lastIdPath:""}}exportMemberBackup(){let j=this.getPathDerivedKey(this.#z),$=this.getIdentitySigningKeyForPath(this.#z);return{name:this.idName,description:this.description,derivedPrivateKey:j.toWif(),address:$.toPublicKey().toAddress(),identityAttributes:this.getAttributes(),identityKey:this.identityKey}}newId(){this.incrementPath();let j=this.getPathDerivedKey(this.#z);return new O(j)}exportMember(){let j=this.exportMemberBackup(),$=this.getPathDerivedKey(this.#z),J=I(v(w(JSON.stringify(j)),$.toPublicKey()));return{wif:j.derivedPrivateKey,encryptedData:J}}}var{toArray:Z,toUTF8:x,toBase64:l,toHex:T}=xj,{electrumEncrypt:n,electrumDecrypt:d}=Mj;class _j{#$;#j;#q;#Q={};#W=H;#J="";#Z="";#z=0;getApiData;constructor(j,$="",J=""){if(!j)throw Error("No key source given");if(typeof j==="string")this.#$=kj.fromString(j),this.#q=!1;else this.#j=Oj.fromWif(j.rootPk),this.#q=!0;if($)this.#J=$;if(J)this.#W=J;this.getApiData=E(this.#W,this.#J)}get lastIdPath(){return this.#Z}getPublicKey(j=""){if(this.#q){if(!this.#j)throw Error("Master private key not initialized");if(j)return this.#j.deriveChild(this.#j.toPublicKey(),j).toPublicKey().toString();return this.#j.toPublicKey().toString()}if(!this.#$)throw Error("HD private key not initialized");if(j)return this.#$.derive(j).pubKey.toString();return this.#$.pubKey.toString()}getHdPublicKey(j=""){if(this.#q)throw Error("HD public keys are not available in Type 42 mode");if(!this.#$)throw Error("HD private key not initialized");if(j)return this.#$.derive(j).toPublic().toString();return this.#$.toPublic().toString()}set BAP_SERVER(j){this.#W=j;for(let $ in this.#Q)this.#Q[$].BAP_SERVER=j}get BAP_SERVER(){return this.#W}set BAP_TOKEN(j){this.#J=j;for(let $ in this.#Q)this.#Q[$].BAP_TOKEN=j}get BAP_TOKEN(){return this.#J}checkIdBelongs(j){let $;if(this.#q){if(!this.#j)throw Error("Master private key not initialized");$=this.#j.deriveChild(this.#j.toPublicKey(),j.rootPath).toPublicKey().toAddress()}else{if(!this.#$)throw Error("HD private key not initialized");$=this.#$.derive(j.rootPath).pubKey.toAddress()}if($!==j.rootAddress)throw Error("ID does not belong to this private key");return!0}listIds(){return Object.keys(this.#Q)}newId(j,$,J={},q=""){let z,Q,W;if(typeof j==="object"||j===void 0||typeof j==="string"&&j.startsWith("/"))Q=typeof j==="string"?j:void 0,W=typeof j==="object"?j:typeof $==="object"?$:{},z="Default Identity";else z=j,Q=typeof $==="string"?$:void 0,W=typeof $==="object"?$:J;let L;if(Q)L=Q;else if(this.#q)L=`bap:${this.#z}`,this.#z++;else L=this.getNextValidPath();let G;if(this.#q){if(!this.#j)throw Error("Type 42 parameters not initialized");G=new U({rootPk:this.#j},W,q)}else{if(!this.#$)throw Error("HD private key not initialized");G=new U(this.#$,W,q)}if(G.BAP_SERVER=this.#W,G.BAP_TOKEN=this.#J,G.idName=z,G.rootPath=L,this.#q)G.currentPath=L;else G.currentPath=X.getNextPath(L);let K=G.getIdentityKey();return this.#Q[K]=G,this.#Z=L,this.#Q[K]}removeId(j){delete this.#Q[j]}getNextValidPath(){if(this.#Z)return X.getNextIdentityPath(this.#Z);return`/0'/${Object.keys(this.#Q).length}'/0'`}newIdWithCounter(j,$=`Identity ${j}`){if(!this.#q)throw Error("newIdWithCounter only works in Type 42 mode");let J=`bap:${j}`;return this.newId($,J)}getId(j){return this.#Q[j]||null}setId(j){this.checkIdBelongs(j),this.#Q[j.getIdentityKey()]=j}importIds(j,$=!0){if($&&typeof j==="string"){this.importEncryptedIds(j);return}let J=j;if(!J.lastIdPath)throw Error("ID cannot be imported as it is not complete");if(!J.ids)throw Error(`ID data is not in the correct format: ${j}`);let q=j.lastIdPath;for(let z of J.ids){if(!z.identityKey||!z.identityAttributes||!z.rootAddress)throw Error("ID cannot be imported as it is not complete");let Q;if(this.#q){if(!this.#j)throw Error("Type 42 parameters not initialized");Q=new U({rootPk:this.#j},{},z.idSeed)}else{if(!this.#$)throw Error("HD private key not initialized");Q=new U(this.#$,{},z.idSeed)}if(Q.BAP_SERVER=this.#W,Q.BAP_TOKEN=this.#J,Q.import(z),q==="")q=Q.currentPath;if(this.checkIdBelongs(Q),this.#Q[Q.getIdentityKey()]=Q,this.#q&&Q.rootPath.startsWith("bap:")){let W=Q.rootPath.split(":");if(W.length>=2){let L=Number.parseInt(W[1],10);if(!Number.isNaN(L))this.#z=Math.max(this.#z,L+1)}}}this.#Z=q}importEncryptedIds(j){let $=this.decrypt(j),J=JSON.parse($);if(Array.isArray(J)){console.log(`Importing old format:
6
+ `,J),this.importOldIds(J);return}if(typeof J!=="object")throw Error("decrypted, but found unrecognized identities format");this.importIds(J,!1)}importOldIds(j){for(let $ of j){let J;if(this.#q){if(!this.#j)throw Error("Type 42 parameters not initialized");J=new U({rootPk:this.#j},{},$.idSeed??"")}else{if(!this.#$)throw Error("HD private key not initialized");J=new U(this.#$,{},$.idSeed??"")}J.BAP_SERVER=this.#W,J.BAP_TOKEN=this.#J,J.import($),this.checkIdBelongs(J),this.#Q[J.getIdentityKey()]=J,this.#Z=J.currentPath}}exportIds(j,$=!0){let J={lastIdPath:this.#Z,ids:[]},q=j||Object.keys(this.#Q);for(let z of q){if(!this.#Q[z])throw Error(`Identity ${z} not found`);J.ids.push(this.#Q[z].export())}if($)return this.encrypt(JSON.stringify(J));return J}exportId(j,$=!0){let J={lastIdPath:this.#Z,ids:[]};if(J.ids.push(this.#Q[j].export()),$)return this.encrypt(JSON.stringify(J));return J}encrypt(j){if(this.#q){if(!this.#j)throw Error("Master private key not initialized");let J=this.#j.deriveChild(this.#j.toPublicKey(),Y);return l(n(Z(j),J.toPublicKey(),null))}if(!this.#$)throw Error("HD private key not initialized");let $=this.#$.derive(Y);return l(n(Z(j),$.pubKey,null))}decrypt(j){if(this.#q){if(!this.#j)throw Error("Master private key not initialized");let J=this.#j.deriveChild(this.#j.toPublicKey(),Y);return x(d(Z(j,"base64"),J))}if(!this.#$)throw Error("HD private key not initialized");let $=this.#$.derive(Y);return x(d(Z(j,"base64"),$.privKey))}signAttestationWithAIP(j,$,J=0,q=""){let z=this.getId($);if(!z)throw Error("Could not find identity to attest with");let Q=this.getAttestationBuffer(j,J,q),{address:W,signature:L}=z.signMessage(Q);return this.createAttestationTransaction(j,J,W,L,q)}verifyAttestationWithAIP(j){if(!j.every((q)=>Array.isArray(q))||j[0][0]!==A.OP_RETURN||T(j[1])!==b)throw Error("Not a valid BAP transaction");let $=T(j[7])==="44415441"?5:0,J={type:x(j[2]),hash:T(j[3]),sequence:x(j[4]),signingProtocol:x(j[7+$]),signingAddress:x(j[8+$]),signature:l(j[9+$])};if($&&j[3]===j[8])J.data=T(j[9]);console.log({attestation:J});try{let q=[];for(let z=0;z<6+$;z++)q.push(j[z]);J.verified=this.verifySignature(q.flat(),J.signingAddress,J.signature)}catch{J.verified=!1}return J}createAttestationTransaction(j,$,J,q,z=""){let Q=[[A.OP_RETURN],Z(f),Z("ATTEST"),Z(j),Z(`${$}`),Z("|")];if(z)Q.push(Z(f),Z("DATA"),Z(j),Z(z),Z("|"));return Q.push(Z(_),Z("BITCOIN_ECDSA"),Z(J),Z(q,"base64")),console.log({elements:Q}),Q}getAttestationBuffer(j,$=0,J=""){let q=[[A.OP_RETURN],Z(f),Z("ATTEST"),Z(j),Z(`${$}`),Z("|")];if(J)q.push(Z(f),Z("DATA"),Z(j),Z(J),Z("|"));return q.flat()}verifySignature(j,$,J){let q;if(Array.isArray(j))q=j;else if(Buffer.isBuffer(j))q=[...j];else q=Z(j,"utf8");let z=Vj.fromCompact(J,"base64"),Q;for(let W=0;W<4;W++)try{if(Q=z.RecoverPublicKey(W,new Uj(g.magicHash(q))),g.verify(q,z,Q)&&Q.toAddress()===$)return!0}catch{}return!1}async verifyChallengeSignature(j,$,J,q){if(!this.verifySignature(J,$,q))return!1;try{let Q=await this.getApiData("/attestation/valid",{idKey:j,address:$,challenge:J,signature:q});if(Q?.status==="success"&&Q?.result?.valid===!0)return!0;return!1}catch(Q){return console.error("API call failed:",Q),!1}}async isValidAttestationTransaction(j){if(this.verifyAttestationWithAIP(j))return this.getApiData("/attestation/valid",{tx:j});return!1}async getIdentityFromAddress(j){return this.getApiData("/identity/from-address",{address:j})}async getIdentity(j){return this.getApiData("/identity/get",{idKey:j})}async getAttestationsForHash(j){return this.getApiData("/attestations",{hash:j})}exportForBackup(j,$,J){let z={ids:this.exportIds(),...j&&{label:j},createdAt:new Date().toISOString()};if(this.#q){if(!this.#j)throw Error("Type 42 parameters not initialized");return{...z,rootPk:this.#j.toWif()}}if(!this.#$)throw Error("HD private key not initialized");return{...z,xprv:$||this.#$.toString(),mnemonic:J||""}}exportMemberForBackup(j,$){let J=this.#Q[j];if(!J)throw Error(`Identity ${j} not found`);let q=J.exportMember();return{wif:q.wif,id:q.encryptedData,...$&&{label:$},createdAt:new Date().toISOString()}}}export{O as MemberID,U as MasterID,_j as BAP};
7
7
 
8
- //# debugId=78F095C16B95FE2864756E2164756E21
8
+ //# debugId=AC86E0751025A3AF64756E2164756E21