@0xpolygonid/js-sdk 1.10.3 → 1.11.0

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.
Files changed (107) hide show
  1. package/README.md +11 -0
  2. package/dist/browser/esm/index.js +8360 -17399
  3. package/dist/browser/esm/index.js.map +1 -1
  4. package/dist/browser/umd/index.js +8381 -17415
  5. package/dist/browser/umd/index.js.map +1 -1
  6. package/dist/node/cjs/blockchain/index.js +17 -0
  7. package/dist/node/cjs/blockchain/transaction-service.js +55 -0
  8. package/dist/node/cjs/credentials/credential-wallet.js +1 -1
  9. package/dist/node/cjs/credentials/status/reverse-sparse-merkle-tree.js +5 -1
  10. package/dist/node/cjs/iden3comm/handlers/auth.js +62 -27
  11. package/dist/node/cjs/iden3comm/handlers/common.js +4 -4
  12. package/dist/node/cjs/iden3comm/handlers/contract-request.js +34 -15
  13. package/dist/node/cjs/iden3comm/handlers/credential-proposal.js +33 -14
  14. package/dist/node/cjs/iden3comm/handlers/fetch.js +65 -34
  15. package/dist/node/cjs/iden3comm/handlers/index.js +1 -0
  16. package/dist/node/cjs/iden3comm/handlers/message-handler.js +96 -0
  17. package/dist/node/cjs/iden3comm/handlers/revocation-status.js +58 -30
  18. package/dist/node/cjs/iden3comm/packageManager.js +16 -0
  19. package/dist/node/cjs/iden3comm/packers/jws.js +63 -49
  20. package/dist/node/cjs/iden3comm/packers/plain.js +13 -3
  21. package/dist/node/cjs/iden3comm/packers/zkp.js +9 -0
  22. package/dist/node/cjs/iden3comm/utils/did.js +11 -11
  23. package/dist/node/cjs/identity/identity-wallet.js +228 -43
  24. package/dist/node/cjs/index.js +1 -0
  25. package/dist/node/cjs/kms/key-providers/bjj-provider.js +9 -0
  26. package/dist/node/cjs/kms/key-providers/ed25519-provider.js +13 -1
  27. package/dist/node/cjs/kms/key-providers/index.js +1 -1
  28. package/dist/node/cjs/kms/key-providers/{sec256k1-provider.js → secp256k1-provider.js} +37 -26
  29. package/dist/node/cjs/kms/kms.js +15 -0
  30. package/dist/node/cjs/proof/proof-service.js +3 -33
  31. package/dist/node/cjs/proof/provers/inputs-generator.js +2 -7
  32. package/dist/node/cjs/proof/verifiers/pub-signals-verifier.js +4 -5
  33. package/dist/node/cjs/storage/blockchain/onchain-revocation.js +4 -12
  34. package/dist/node/cjs/storage/blockchain/onchain-zkp-verifier.js +3 -10
  35. package/dist/node/cjs/storage/blockchain/state.js +39 -10
  36. package/dist/node/cjs/utils/did-helper.js +36 -2
  37. package/dist/node/cjs/verifiable/constants.js +2 -1
  38. package/dist/node/esm/blockchain/index.js +1 -0
  39. package/dist/node/esm/blockchain/transaction-service.js +51 -0
  40. package/dist/node/esm/credentials/credential-wallet.js +1 -1
  41. package/dist/node/esm/credentials/status/reverse-sparse-merkle-tree.js +6 -2
  42. package/dist/node/esm/iden3comm/handlers/auth.js +62 -27
  43. package/dist/node/esm/iden3comm/handlers/common.js +4 -4
  44. package/dist/node/esm/iden3comm/handlers/contract-request.js +34 -15
  45. package/dist/node/esm/iden3comm/handlers/credential-proposal.js +33 -14
  46. package/dist/node/esm/iden3comm/handlers/fetch.js +65 -34
  47. package/dist/node/esm/iden3comm/handlers/index.js +1 -0
  48. package/dist/node/esm/iden3comm/handlers/message-handler.js +91 -0
  49. package/dist/node/esm/iden3comm/handlers/revocation-status.js +58 -30
  50. package/dist/node/esm/iden3comm/packageManager.js +16 -0
  51. package/dist/node/esm/iden3comm/packers/jws.js +63 -49
  52. package/dist/node/esm/iden3comm/packers/plain.js +13 -3
  53. package/dist/node/esm/iden3comm/packers/zkp.js +9 -0
  54. package/dist/node/esm/iden3comm/utils/did.js +11 -8
  55. package/dist/node/esm/identity/identity-wallet.js +230 -45
  56. package/dist/node/esm/index.js +1 -0
  57. package/dist/node/esm/kms/key-providers/bjj-provider.js +10 -1
  58. package/dist/node/esm/kms/key-providers/ed25519-provider.js +13 -1
  59. package/dist/node/esm/kms/key-providers/index.js +1 -1
  60. package/dist/node/esm/kms/key-providers/secp256k1-provider.js +85 -0
  61. package/dist/node/esm/kms/kms.js +15 -0
  62. package/dist/node/esm/proof/proof-service.js +4 -34
  63. package/dist/node/esm/proof/provers/inputs-generator.js +3 -8
  64. package/dist/node/esm/proof/verifiers/pub-signals-verifier.js +4 -5
  65. package/dist/node/esm/storage/blockchain/onchain-revocation.js +4 -12
  66. package/dist/node/esm/storage/blockchain/onchain-zkp-verifier.js +3 -10
  67. package/dist/node/esm/storage/blockchain/state.js +39 -10
  68. package/dist/node/esm/utils/did-helper.js +33 -1
  69. package/dist/node/esm/verifiable/constants.js +2 -1
  70. package/dist/types/blockchain/index.d.ts +1 -0
  71. package/dist/types/blockchain/transaction-service.d.ts +80 -0
  72. package/dist/types/iden3comm/handlers/auth.d.ts +17 -2
  73. package/dist/types/iden3comm/handlers/common.d.ts +2 -2
  74. package/dist/types/iden3comm/handlers/contract-request.d.ts +10 -2
  75. package/dist/types/iden3comm/handlers/credential-proposal.d.ts +5 -2
  76. package/dist/types/iden3comm/handlers/fetch.d.ts +15 -6
  77. package/dist/types/iden3comm/handlers/index.d.ts +1 -0
  78. package/dist/types/iden3comm/handlers/message-handler.d.ts +83 -0
  79. package/dist/types/iden3comm/handlers/revocation-status.d.ts +18 -2
  80. package/dist/types/iden3comm/packageManager.d.ts +10 -0
  81. package/dist/types/iden3comm/packers/jws.d.ts +9 -0
  82. package/dist/types/iden3comm/packers/plain.d.ts +10 -2
  83. package/dist/types/iden3comm/packers/zkp.d.ts +7 -0
  84. package/dist/types/iden3comm/types/packageManager.d.ts +10 -0
  85. package/dist/types/iden3comm/types/packer.d.ts +24 -2
  86. package/dist/types/iden3comm/types/protocol/auth.d.ts +5 -15
  87. package/dist/types/iden3comm/types/protocol/contract-request.d.ts +2 -6
  88. package/dist/types/iden3comm/types/protocol/credentials.d.ts +7 -44
  89. package/dist/types/iden3comm/types/protocol/messages.d.ts +2 -9
  90. package/dist/types/iden3comm/types/protocol/proof.d.ts +3 -16
  91. package/dist/types/iden3comm/types/protocol/revocation.d.ts +3 -16
  92. package/dist/types/identity/identity-wallet.d.ts +80 -7
  93. package/dist/types/index.d.ts +1 -0
  94. package/dist/types/kms/key-providers/bjj-provider.d.ts +1 -0
  95. package/dist/types/kms/key-providers/ed25519-provider.d.ts +8 -0
  96. package/dist/types/kms/key-providers/index.d.ts +1 -1
  97. package/dist/types/kms/key-providers/{sec256k1-provider.d.ts → secp256k1-provider.d.ts} +15 -9
  98. package/dist/types/kms/kms.d.ts +18 -0
  99. package/dist/types/proof/proof-service.d.ts +2 -2
  100. package/dist/types/storage/blockchain/onchain-revocation.d.ts +1 -0
  101. package/dist/types/storage/blockchain/state.d.ts +7 -2
  102. package/dist/types/storage/interfaces/state.d.ts +26 -2
  103. package/dist/types/utils/did-helper.d.ts +9 -1
  104. package/dist/types/verifiable/constants.d.ts +1 -0
  105. package/package.json +10 -12
  106. package/LICENSE +0 -691
  107. package/dist/node/esm/kms/key-providers/sec256k1-provider.js +0 -71
@@ -8,6 +8,18 @@ import { byteDecoder, byteEncoder } from '../../utils';
8
8
  * @implements implements IPacker interface
9
9
  */
10
10
  export class PlainPacker {
11
+ /**
12
+ * Packs a basic message using the specified parameters.
13
+ *
14
+ * @param msg - The basic message to pack.
15
+ * @param param - The packer parameters.
16
+ * @returns A promise that resolves to a Uint8Array representing the packed message.
17
+ * @throws An error if the method is not implemented.
18
+ */
19
+ packMessage(msg) {
20
+ msg.typ = MediaType.PlainMessage;
21
+ return Promise.resolve(byteEncoder.encode(JSON.stringify(msg)));
22
+ }
11
23
  /**
12
24
  * Pack returns packed message to transport envelope
13
25
  *
@@ -15,9 +27,7 @@ export class PlainPacker {
15
27
  * @param {PlainPackerParams} _params - not used here
16
28
  * @returns `Promise<Uint8Array>`
17
29
  */
18
- //
19
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
20
- async pack(payload, _params) {
30
+ async pack(payload) {
21
31
  const msg = JSON.parse(byteDecoder.decode(payload));
22
32
  msg.typ = MediaType.PlainMessage;
23
33
  return Promise.resolve(byteEncoder.encode(JSON.stringify(msg)));
@@ -74,6 +74,15 @@ export class ZKPPacker {
74
74
  this.provingParamsMap = provingParamsMap;
75
75
  this.verificationParamsMap = verificationParamsMap;
76
76
  }
77
+ /**
78
+ * Packs a basic message using the specified parameters.
79
+ * @param msg - The basic message to pack.
80
+ * @param param - The parameters for the ZKPPacker.
81
+ * @returns A promise that resolves to a Uint8Array representing the packed message.
82
+ */
83
+ packMessage(msg, param) {
84
+ return this.pack(byteEncoder.encode(JSON.stringify(msg)), param);
85
+ }
77
86
  /**
78
87
  * creates JSON Web Zeroknowledge token
79
88
  *
@@ -1,5 +1,5 @@
1
1
  import { SUPPORTED_PUBLIC_KEY_TYPES } from '../constants';
2
- import elliptic from 'elliptic';
2
+ import { secp256k1 as sec } from '@noble/curves/secp256k1';
3
3
  import { KmsKeyType } from '../../kms';
4
4
  import { base58ToBytes, base64UrlToBytes, bytesToHex, hexToBytes } from '../../utils';
5
5
  const DIDAuthenticationSection = 'authentication';
@@ -23,7 +23,6 @@ export const resolveVerificationMethods = (didDocument) => {
23
23
  }
24
24
  return sortedVerificationMethods;
25
25
  };
26
- const secp256k1 = new elliptic.ec('secp256k1');
27
26
  export const extractPublicKeyBytes = (vm) => {
28
27
  const isSupportedVmType = Object.keys(SUPPORTED_PUBLIC_KEY_TYPES).some((key) => SUPPORTED_PUBLIC_KEY_TYPES[key].includes(vm.type));
29
28
  if (vm.publicKeyBase58 && isSupportedVmType) {
@@ -42,13 +41,17 @@ export const extractPublicKeyBytes = (vm) => {
42
41
  vm.publicKeyJwk.crv === 'secp256k1' &&
43
42
  vm.publicKeyJwk.x &&
44
43
  vm.publicKeyJwk.y) {
44
+ const [xHex, yHex] = [
45
+ base64UrlToBytes(vm.publicKeyJwk.x),
46
+ base64UrlToBytes(vm.publicKeyJwk.y)
47
+ ].map(bytesToHex);
48
+ const x = xHex.includes('0x') ? BigInt(xHex) : BigInt(`0x${xHex}`);
49
+ const y = yHex.includes('0x') ? BigInt(yHex) : BigInt(`0x${yHex}`);
45
50
  return {
46
- publicKeyBytes: hexToBytes(secp256k1
47
- .keyFromPublic({
48
- x: bytesToHex(base64UrlToBytes(vm.publicKeyJwk.x)),
49
- y: bytesToHex(base64UrlToBytes(vm.publicKeyJwk.y))
50
- })
51
- .getPublic('hex')),
51
+ publicKeyBytes: sec.ProjectivePoint.fromAffine({
52
+ x,
53
+ y
54
+ }).toRawBytes(false),
52
55
  kmsKeyType: KmsKeyType.Secp256k1
53
56
  };
54
57
  }
@@ -1,6 +1,6 @@
1
1
  import { KmsKeyType } from '../kms';
2
2
  import { Blockchain, buildDIDType, BytesHelper, Claim, ClaimOptions, DID, DidMethod, getUnixTimestamp, Id, NetworkId, SchemaHash } from '@iden3/js-iden3-core';
3
- import { poseidon, PublicKey, sha256, Signature, Hex, getRandomBytes } from '@iden3/js-crypto';
3
+ import { poseidon, PublicKey, sha256, Signature, Hex, getRandomBytes, Poseidon } from '@iden3/js-crypto';
4
4
  import { hashElems, ZERO_HASH } from '@iden3/js-merkletree';
5
5
  import { generateProfileDID, subjectPositionIndex } from './common';
6
6
  import * as uuid from 'uuid';
@@ -8,8 +8,11 @@ import { JsonSchemaValidator, cacheLoader } from '../schema-processor';
8
8
  import { MerkleTreeType } from '../storage';
9
9
  import { VerifiableConstants, BJJSignatureProof2021, MerklizedRootPosition, SubjectPosition, W3CCredential, Iden3SparseMerkleTreeProof, ProofType, CredentialStatusType } from '../verifiable';
10
10
  import { getKMSIdByAuthCredential, getNodesRepresentation, pushHashesToRHS } from '../credentials';
11
- import { byteEncoder } from '../utils';
11
+ import { CircuitId, StateTransitionInputs } from '../circuits';
12
+ import { buildDIDFromEthPubKey, byteEncoder, isEthereumIdentity } from '../utils';
12
13
  import { CredentialStatusPublisherRegistry, Iden3SmtRhsCredentialStatusPublisher } from '../credentials/status/credential-status-publisher';
14
+ import { InputGenerator } from '../proof';
15
+ import { TransactionService } from '../blockchain';
13
16
  /**
14
17
  * @public
15
18
  * Wallet instance to manage the digital identity based on iden3 protocol
@@ -36,6 +39,8 @@ export class IdentityWallet {
36
39
  this._credentialWallet = _credentialWallet;
37
40
  this._opts = _opts;
38
41
  this._credentialStatusPublisherRegistry = this.getCredentialStatusPublisherRegistry(_opts);
42
+ this._inputsGenerator = new InputGenerator(this, _credentialWallet, _storage.states);
43
+ this._transactionService = new TransactionService(_storage.states.getRpcProvider());
39
44
  }
40
45
  getCredentialStatusPublisherRegistry(_opts) {
41
46
  if (!_opts?.credentialStatusPublisherRegistry) {
@@ -50,35 +55,16 @@ export class IdentityWallet {
50
55
  return this._opts?.credentialStatusPublisherRegistry;
51
56
  }
52
57
  }
53
- /**
54
- * {@inheritDoc IIdentityWallet.createIdentity}
55
- */
56
- async createIdentity(opts) {
57
- const tmpIdentifier = opts.seed ? uuid.v5(Hex.encode(sha256(opts.seed)), uuid.NIL) : uuid.v4();
58
- opts.method = opts.method ?? DidMethod.Iden3;
59
- opts.blockchain = opts.blockchain ?? Blockchain.Polygon;
60
- opts.networkId = opts.networkId ?? NetworkId.Amoy;
61
- await this._storage.mt.createIdentityMerkleTrees(tmpIdentifier);
62
- opts.seed = opts.seed ?? getRandomBytes(32);
63
- const keyId = await this._kms.createKeyFromSeed(KmsKeyType.BabyJubJub, opts.seed);
58
+ async createAuthCoreClaim(revNonce, seed) {
59
+ const keyId = await this._kms.createKeyFromSeed(KmsKeyType.BabyJubJub, seed);
64
60
  const pubKeyHex = await this._kms.publicKey(keyId);
65
61
  const pubKey = PublicKey.newFromHex(pubKeyHex);
66
62
  const schemaHash = SchemaHash.authSchemaHash;
67
63
  const authClaim = Claim.newClaim(schemaHash, ClaimOptions.withIndexDataInts(pubKey.p[0], pubKey.p[1]), ClaimOptions.withRevocationNonce(BigInt(0)));
68
- const revNonce = opts.revocationOpts.nonce ?? 0;
69
64
  authClaim.setRevocationNonce(BigInt(revNonce));
70
- await this._storage.mt.addToMerkleTree(tmpIdentifier, MerkleTreeType.Claims, authClaim.hiHv().hi, authClaim.hiHv().hv);
71
- const claimsTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(tmpIdentifier, MerkleTreeType.Claims);
72
- const currentState = hashElems([
73
- (await claimsTree.root()).bigInt(),
74
- ZERO_HASH.bigInt(),
75
- ZERO_HASH.bigInt()
76
- ]);
77
- const didType = buildDIDType(opts.method, opts.blockchain, opts.networkId);
78
- const identifier = Id.idGenesisFromIdenState(didType, currentState.bigInt());
79
- const did = DID.parseFromId(identifier);
80
- await this._storage.mt.bindMerkleTreeToNewIdentifier(tmpIdentifier, did.string());
81
- const schema = JSON.parse(VerifiableConstants.AUTH.AUTH_BJJ_CREDENTIAL_SCHEMA_JSON);
65
+ return { authClaim, pubKey };
66
+ }
67
+ async createAuthBJJCredential(did, pubKey, authClaim, currentState, revocationOpts) {
82
68
  const authData = authClaim.getExpirationDate();
83
69
  const expiration = authData ? getUnixTimestamp(authData) : 0;
84
70
  const request = {
@@ -92,29 +78,91 @@ export class IdentityWallet {
92
78
  version: 0,
93
79
  expiration,
94
80
  revocationOpts: {
95
- nonce: revNonce,
96
- id: opts.revocationOpts.id.replace(/\/$/, ''),
97
- type: opts.revocationOpts.type,
81
+ nonce: Number(authClaim.getRevocationNonce()),
82
+ id: revocationOpts.id.replace(/\/$/, ''),
83
+ type: revocationOpts.type,
98
84
  issuerState: currentState.hex()
99
85
  }
100
86
  };
87
+ // Check if has already an auth credential
88
+ const authCredentials = await this._credentialWallet.getAllAuthBJJCredentials(did);
101
89
  let credential = new W3CCredential();
102
- try {
103
- credential = this._credentialWallet.createCredential(did, request, schema);
90
+ if (authCredentials.length === 0) {
91
+ const schema = JSON.parse(VerifiableConstants.AUTH.AUTH_BJJ_CREDENTIAL_SCHEMA_JSON);
92
+ try {
93
+ credential = this._credentialWallet.createCredential(did, request, schema);
94
+ }
95
+ catch (e) {
96
+ throw new Error(`Error create w3c credential ${e.message}`);
97
+ }
104
98
  }
105
- catch (e) {
106
- throw new Error(`Error create w3c credential ${e.message}`);
99
+ else {
100
+ // credential with sigProof signed with previous auth bjj credential
101
+ credential = await this.issueCredential(did, request);
107
102
  }
108
- const index = authClaim.hIndex();
103
+ return credential;
104
+ }
105
+ /**
106
+ * {@inheritDoc IIdentityWallet.createIdentity}
107
+ */
108
+ async createIdentity(opts) {
109
+ const tmpIdentifier = opts.seed ? uuid.v5(Hex.encode(sha256(opts.seed)), uuid.NIL) : uuid.v4();
110
+ opts.seed = opts.seed ?? getRandomBytes(32);
111
+ await this._storage.mt.createIdentityMerkleTrees(tmpIdentifier);
112
+ const revNonce = opts.revocationOpts.nonce ?? 0;
113
+ const { authClaim, pubKey } = await this.createAuthCoreClaim(revNonce, opts.seed);
114
+ const { hi, hv } = authClaim.hiHv();
115
+ await this._storage.mt.addToMerkleTree(tmpIdentifier, MerkleTreeType.Claims, hi, hv);
116
+ const claimsTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(tmpIdentifier, MerkleTreeType.Claims);
109
117
  const ctr = await claimsTree.root();
118
+ const currentState = hashElems([ctr.bigInt(), ZERO_HASH.bigInt(), ZERO_HASH.bigInt()]);
119
+ const didType = buildDIDType(opts.method || DidMethod.Iden3, opts.blockchain || Blockchain.Polygon, opts.networkId || NetworkId.Amoy);
120
+ const identifier = Id.idGenesisFromIdenState(didType, currentState.bigInt());
121
+ const did = DID.parseFromId(identifier);
122
+ await this._storage.mt.bindMerkleTreeToNewIdentifier(tmpIdentifier, did.string());
123
+ const oldTreeState = {
124
+ revocationRoot: ZERO_HASH,
125
+ claimsRoot: ctr,
126
+ state: currentState,
127
+ rootOfRoots: ZERO_HASH
128
+ };
129
+ const identity = await this._storage.identity.getIdentity(did.string());
130
+ if (!identity) {
131
+ await this._storage.identity.saveIdentity({
132
+ did: did.string(),
133
+ state: currentState,
134
+ isStatePublished: false,
135
+ isStateGenesis: true
136
+ });
137
+ }
138
+ // check whether we have auth credential, if not - create a new one
139
+ const credentials = await this._credentialWallet.findByQuery({
140
+ credentialSubject: {
141
+ x: {
142
+ $eq: pubKey.p[0].toString()
143
+ },
144
+ y: {
145
+ $eq: pubKey.p[1].toString()
146
+ }
147
+ },
148
+ allowedIssuers: [did.string()]
149
+ });
150
+ if (credentials.length) {
151
+ return {
152
+ did,
153
+ credential: credentials[0]
154
+ };
155
+ }
156
+ const credential = await this.createAuthBJJCredential(did, pubKey, authClaim, currentState, opts.revocationOpts);
157
+ const index = authClaim.hIndex();
110
158
  const { proof } = await claimsTree.generateProof(index, ctr);
111
159
  const mtpProof = new Iden3SparseMerkleTreeProof({
112
160
  mtp: proof,
113
161
  issuerData: {
114
162
  id: did,
115
163
  state: {
116
- rootOfRoots: ZERO_HASH,
117
- revocationTreeRoot: ZERO_HASH,
164
+ rootOfRoots: oldTreeState.rootOfRoots,
165
+ revocationTreeRoot: oldTreeState.revocationRoot,
118
166
  claimsTreeRoot: ctr,
119
167
  value: currentState
120
168
  }
@@ -126,13 +174,45 @@ export class IdentityWallet {
126
174
  rhsUrl: opts.revocationOpts.id,
127
175
  onChain: opts.revocationOpts.onChain
128
176
  });
177
+ await this._credentialWallet.save(credential);
178
+ return {
179
+ did,
180
+ credential
181
+ };
182
+ }
183
+ /**
184
+ * {@inheritDoc IIdentityWallet.createEthereumBasedIdentity}
185
+ */
186
+ async createEthereumBasedIdentity(opts) {
187
+ opts.seed = opts.seed ?? getRandomBytes(32);
188
+ opts.createBjjCredential = opts.createBjjCredential ?? true;
189
+ let credential;
190
+ const ethSigner = opts.ethSigner;
191
+ if (!ethSigner) {
192
+ throw new Error('Ethereum signer is required to create Ethereum identities in order to transit state');
193
+ }
194
+ const currentState = ZERO_HASH; // In Ethereum identities we don't have an initial state with the auth credential
195
+ const didType = buildDIDType(opts.method || DidMethod.Iden3, opts.blockchain || Blockchain.Polygon, opts.networkId || NetworkId.Amoy);
196
+ const keyIdEth = await this._kms.createKeyFromSeed(KmsKeyType.Secp256k1, opts.seed);
197
+ const pubKeyHexEth = (await this._kms.publicKey(keyIdEth)).slice(2); // 04 + x + y (uncompressed key)
198
+ const did = buildDIDFromEthPubKey(didType, pubKeyHexEth);
199
+ await this._storage.mt.createIdentityMerkleTrees(did.string());
129
200
  await this._storage.identity.saveIdentity({
130
201
  did: did.string(),
131
202
  state: currentState,
132
203
  isStatePublished: false,
133
204
  isStateGenesis: true
134
205
  });
135
- await this._credentialWallet.save(credential);
206
+ if (opts.createBjjCredential) {
207
+ // Old tree state genesis state
208
+ const oldTreeState = {
209
+ revocationRoot: ZERO_HASH,
210
+ claimsRoot: ZERO_HASH,
211
+ state: currentState,
212
+ rootOfRoots: ZERO_HASH
213
+ };
214
+ credential = await this.addBJJAuthCredential(did, oldTreeState, true, ethSigner, opts);
215
+ }
136
216
  return {
137
217
  did,
138
218
  credential
@@ -206,7 +286,10 @@ export class IdentityWallet {
206
286
  /** {@inheritDoc IIdentityWallet.generateClaimMtp} */
207
287
  async generateCredentialMtp(did, credential, treeState) {
208
288
  const coreClaim = await this.getCoreClaimFromCredential(credential);
209
- // todo: Parser.parseClaim
289
+ return this.generateCoreClaimMtp(did, coreClaim, treeState);
290
+ }
291
+ /** {@inheritDoc IIdentityWallet.generateClaimMtp} */
292
+ async generateCoreClaimMtp(did, coreClaim, treeState) {
210
293
  const treesModel = await this.getDIDTreeModel(did);
211
294
  const claimsTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(did.string(), MerkleTreeType.Claims);
212
295
  const claimsRoot = await treesModel.claimsTree.root();
@@ -340,14 +423,14 @@ export class IdentityWallet {
340
423
  };
341
424
  }
342
425
  }
343
- throw new Error('no auth credentials found');
426
+ throw new Error(VerifiableConstants.ERRORS.NO_AUTH_CRED_FOUND);
344
427
  }
345
428
  /** {@inheritDoc IIdentityWallet.revokeCredential} */
346
429
  async revokeCredential(issuerDID, credential) {
347
430
  const issuerTree = await this.getDIDTreeModel(issuerDID);
348
- const coreClaim = credential.getCoreClaimFromProof(ProofType.BJJSignature);
431
+ const coreClaim = await this.getCoreClaimFromCredential(credential);
349
432
  if (!coreClaim) {
350
- throw new Error('credential must have coreClaim representation in the signature proof');
433
+ throw new Error('credential must have coreClaim representation in proofs');
351
434
  }
352
435
  const nonce = coreClaim.getRevocationNonce();
353
436
  await issuerTree.revocationTree.add(nonce, BigInt(0));
@@ -394,16 +477,17 @@ export class IdentityWallet {
394
477
  }
395
478
  /** {@inheritDoc IIdentityWallet.generateIden3SparseMerkleTreeProof} */
396
479
  // treeState - optional, if it is not passed proof of claim inclusion will be generated on the latest state in the tree.
397
- async generateIden3SparseMerkleTreeProof(issuerDID, credentials, txId, blockNumber, blockTimestamp, treeState) {
480
+ async generateIden3SparseMerkleTreeProof(issuerDID, credentials, txId, blockNumber, blockTimestamp, treeState, opts) {
398
481
  for (let index = 0; index < credentials.length; index++) {
399
482
  const credential = credentials[index];
400
- const mtpWithProof = await this.generateCredentialMtp(issuerDID, credential, treeState);
401
483
  // TODO: return coreClaim from generateCredentialMtp and use it below
402
484
  // credential must have a bjj signature proof
403
- const coreClaim = credential.getCoreClaimFromProof(ProofType.BJJSignature);
485
+ const coreClaim = credential.getCoreClaimFromProof(ProofType.BJJSignature) ||
486
+ (await credential.toCoreClaim(opts));
404
487
  if (!coreClaim) {
405
488
  throw new Error('credential must have coreClaim representation in the signature proof');
406
489
  }
490
+ const mtpWithProof = await this.generateCoreClaimMtp(issuerDID, coreClaim, treeState);
407
491
  const mtpProof = new Iden3SparseMerkleTreeProof({
408
492
  mtp: mtpWithProof.proof,
409
493
  issuerData: {
@@ -424,7 +508,9 @@ export class IdentityWallet {
424
508
  credentials[index].proof.push(mtpProof);
425
509
  }
426
510
  else {
427
- credentials[index].proof = [credentials[index].proof, mtpProof];
511
+ credentials[index].proof = credentials[index].proof
512
+ ? [credentials[index].proof, mtpProof]
513
+ : [mtpProof];
428
514
  }
429
515
  }
430
516
  return credentials;
@@ -513,4 +599,103 @@ export class IdentityWallet {
513
599
  isStateGenesis: false
514
600
  });
515
601
  }
602
+ /** {@inheritdoc IIdentityWallet.transitState} */
603
+ async transitState(did, oldTreeState, isOldStateGenesis, ethSigner, prover) {
604
+ const newTreeModel = await this.getDIDTreeModel(did);
605
+ const claimsRoot = await newTreeModel.claimsTree.root();
606
+ const rootOfRoots = await newTreeModel.rootsTree.root();
607
+ const revocationRoot = await newTreeModel.revocationTree.root();
608
+ const newTreeState = {
609
+ revocationRoot,
610
+ claimsRoot,
611
+ state: newTreeModel.state,
612
+ rootOfRoots
613
+ };
614
+ const userId = DID.idFromDID(did);
615
+ let proof;
616
+ const isEthIdentity = isEthereumIdentity(did); // don't generate proof for ethereum identities
617
+ let txId;
618
+ if (!isEthIdentity) {
619
+ if (!prover) {
620
+ throw new Error('prover is required to generate proofs for non ethereum identities');
621
+ }
622
+ // generate the proof
623
+ const authInfo = await this._inputsGenerator.prepareAuthBJJCredential(did, oldTreeState);
624
+ const challenge = Poseidon.hash([oldTreeState.state.bigInt(), newTreeState.state.bigInt()]);
625
+ const signature = await this.signChallenge(challenge, authInfo.credential);
626
+ const circuitInputs = new StateTransitionInputs();
627
+ circuitInputs.id = userId;
628
+ circuitInputs.signature = signature;
629
+ circuitInputs.isOldStateGenesis = isOldStateGenesis;
630
+ const authClaimIncProofNewState = await this.generateCredentialMtp(did, authInfo.credential, newTreeState);
631
+ circuitInputs.newTreeState = authClaimIncProofNewState.treeState;
632
+ circuitInputs.authClaimNewStateIncProof = authClaimIncProofNewState.proof;
633
+ circuitInputs.oldTreeState = oldTreeState;
634
+ circuitInputs.authClaim = {
635
+ claim: authInfo.coreClaim,
636
+ incProof: authInfo.incProof,
637
+ nonRevProof: authInfo.nonRevProof
638
+ };
639
+ const inputs = circuitInputs.inputsMarshal();
640
+ proof = await prover.generate(inputs, CircuitId.StateTransition);
641
+ txId = await this._storage.states.publishState(proof, ethSigner);
642
+ }
643
+ else {
644
+ const oldUserState = oldTreeState.state;
645
+ const newUserState = newTreeState.state;
646
+ const userStateTransitionInfo = {
647
+ userId,
648
+ oldUserState,
649
+ newUserState,
650
+ isOldStateGenesis,
651
+ methodId: BigInt(1),
652
+ methodParams: '0x'
653
+ };
654
+ txId = await this._storage.states.publishStateGeneric(ethSigner, userStateTransitionInfo);
655
+ }
656
+ await this.updateIdentityState(did, true, newTreeState);
657
+ return txId;
658
+ }
659
+ /** {@inheritdoc IIdentityWallet.addBJJAuthCredential} */
660
+ async addBJJAuthCredential(did, oldTreeState, isOldStateGenesis, ethSigner, opts, prover // it will be needed in case of non ethereum identities
661
+ ) {
662
+ opts.seed = opts.seed ?? getRandomBytes(32);
663
+ opts.revocationOpts.nonce =
664
+ opts.revocationOpts.nonce ??
665
+ (isOldStateGenesis
666
+ ? 0
667
+ : opts.revocationOpts.nonce ?? new DataView(getRandomBytes(12).buffer).getUint32(0));
668
+ const { authClaim, pubKey } = await this.createAuthCoreClaim(opts.revocationOpts.nonce ?? 0, opts.seed);
669
+ const { hi, hv } = authClaim.hiHv();
670
+ await this._storage.mt.addToMerkleTree(did.string(), MerkleTreeType.Claims, hi, hv);
671
+ // Calculate current state after adding credential to merkle tree
672
+ const claimsTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(did.string(), MerkleTreeType.Claims);
673
+ const currentState = hashElems([
674
+ (await claimsTree.root()).bigInt(),
675
+ oldTreeState.revocationRoot.bigInt(),
676
+ oldTreeState.rootOfRoots.bigInt()
677
+ ]);
678
+ let credential = await this.createAuthBJJCredential(did, pubKey, authClaim, currentState, opts.revocationOpts);
679
+ const txId = await this.transitState(did, oldTreeState, isOldStateGenesis, ethSigner, prover);
680
+ const { receipt, block } = await this._transactionService.getTransactionReceiptAndBlock(txId);
681
+ const credsWithIden3MTPProof = await this.generateIden3SparseMerkleTreeProof(did, [credential], txId, receipt?.blockNumber, block?.timestamp, undefined, {
682
+ revNonce: Number(authClaim.getRevocationNonce()),
683
+ subjectPosition: SubjectPosition.None,
684
+ merklizedRootPosition: MerklizedRootPosition.None,
685
+ updatable: false,
686
+ version: 0,
687
+ merklizeOpts: { documentLoader: cacheLoader() }
688
+ });
689
+ await this._credentialWallet.saveAll(credsWithIden3MTPProof);
690
+ const credRefreshed = await this._credentialWallet.findById(credential.id);
691
+ if (!credRefreshed) {
692
+ throw new Error('Credential not found in credential wallet');
693
+ }
694
+ credential = credRefreshed;
695
+ await this.publishRevocationInfoByCredentialStatusType(did, opts.revocationOpts.type, {
696
+ rhsUrl: opts.revocationOpts.id,
697
+ onChain: opts.revocationOpts.onChain
698
+ });
699
+ return credential;
700
+ }
516
701
  }
@@ -9,6 +9,7 @@ export * from './iden3comm';
9
9
  export * from './circuits';
10
10
  export * from './iden3comm';
11
11
  export * from './utils';
12
+ export * from './blockchain';
12
13
  import * as core from '@iden3/js-iden3-core';
13
14
  import * as jsonLDMerklizer from '@iden3/js-jsonld-merklization';
14
15
  export { core };
@@ -1,6 +1,8 @@
1
- import { Hex, PrivateKey } from '@iden3/js-crypto';
1
+ import { Hex, PrivateKey, PublicKey, Signature } from '@iden3/js-crypto';
2
2
  import { BytesHelper, checkBigIntInField } from '@iden3/js-iden3-core';
3
+ import { KmsKeyType } from '../store';
3
4
  import * as providerHelpers from '../provider-helpers';
5
+ import { hexToBytes } from '../../utils';
4
6
  /**
5
7
  * Provider for Baby Jub Jub keys
6
8
  * @public
@@ -14,6 +16,9 @@ export class BjjProvider {
14
16
  * @param {AbstractPrivateKeyStore} keyStore - key store for kms
15
17
  */
16
18
  constructor(keyType, keyStore) {
19
+ if (keyType !== KmsKeyType.BabyJubJub) {
20
+ throw new Error('Key type must be BabyJubJub');
21
+ }
17
22
  this.keyType = keyType;
18
23
  this.keyStore = keyStore;
19
24
  }
@@ -68,4 +73,8 @@ export class BjjProvider {
68
73
  const privateKeyHex = await this.keyStore.get({ alias: keyId.id });
69
74
  return new PrivateKey(Hex.decodeString(privateKeyHex));
70
75
  }
76
+ async verify(message, signatureHex, keyId) {
77
+ const publicKey = await this.publicKey(keyId);
78
+ return PublicKey.newFromCompressed(hexToBytes(publicKey)).verifyPoseidon(BytesHelper.bytesToInt(message), Signature.newFromCompressed(hexToBytes(signatureHex)));
79
+ }
71
80
  }
@@ -1,6 +1,7 @@
1
1
  import * as providerHelpers from '../provider-helpers';
2
2
  import { ed25519 } from '@noble/curves/ed25519';
3
3
  import { bytesToHex } from '../../utils';
4
+ import { sha256 } from '@iden3/js-crypto';
4
5
  /**
5
6
  * Provider for Ed25519 keys
6
7
  * @public
@@ -56,7 +57,18 @@ export class Ed25519Provider {
56
57
  */
57
58
  async sign(keyId, data) {
58
59
  const privateKeyHex = await this.privateKey(keyId);
59
- return ed25519.sign(data, privateKeyHex);
60
+ return ed25519.sign(sha256(data), privateKeyHex);
61
+ }
62
+ /**
63
+ * Verifies a signature for the given message and key identifier.
64
+ * @param message - The message to verify the signature against.
65
+ * @param signatureHex - The signature to verify, as a hexadecimal string.
66
+ * @param keyId - The key identifier to use for verification.
67
+ * @returns A Promise that resolves to a boolean indicating whether the signature is valid.
68
+ */
69
+ async verify(message, signatureHex, keyId) {
70
+ const publicKeyHex = await this.publicKey(keyId);
71
+ return ed25519.verify(signatureHex, sha256(message), publicKeyHex);
60
72
  }
61
73
  /**
62
74
  * Retrieves the private key for a given keyId from the key store.
@@ -1,3 +1,3 @@
1
1
  export * from './bjj-provider';
2
2
  export * from './ed25519-provider';
3
- export * from './sec256k1-provider';
3
+ export * from './secp256k1-provider';
@@ -0,0 +1,85 @@
1
+ import { KmsKeyType } from '../store';
2
+ import * as providerHelpers from '../provider-helpers';
3
+ import { base64UrlToBytes, bytesToHex } from '../../utils';
4
+ import { secp256k1 } from '@noble/curves/secp256k1';
5
+ import { sha256 } from '@iden3/js-crypto';
6
+ import { ES256KSigner, hexToBytes } from 'did-jwt';
7
+ /**
8
+ * Provider for Secp256k1
9
+ * @public
10
+ * @class Secp256k1Provider
11
+ * @implements implements IKeyProvider interface
12
+ */
13
+ export class Sec256k1Provider {
14
+ /**
15
+ * Creates an instance of BjjProvider.
16
+ * @param {KmsKeyType} keyType - kms key type
17
+ * @param {AbstractPrivateKeyStore} keyStore - key store for kms
18
+ */
19
+ constructor(keyType, keyStore) {
20
+ if (keyType !== KmsKeyType.Secp256k1) {
21
+ throw new Error('Key type must be Secp256k1');
22
+ }
23
+ this.keyType = keyType;
24
+ this._keyStore = keyStore;
25
+ }
26
+ /**
27
+ * generates a baby jub jub key from a seed phrase
28
+ * @param {Uint8Array} seed - byte array seed
29
+ * @returns kms key identifier
30
+ */
31
+ async newPrivateKeyFromSeed(seed) {
32
+ if (seed.length !== 32) {
33
+ throw new Error('Seed should be 32 bytes');
34
+ }
35
+ const publicKey = secp256k1.getPublicKey(seed);
36
+ const kmsId = {
37
+ type: this.keyType,
38
+ id: providerHelpers.keyPath(this.keyType, bytesToHex(publicKey))
39
+ };
40
+ await this._keyStore.importKey({
41
+ alias: kmsId.id,
42
+ key: bytesToHex(seed).padStart(64, '0')
43
+ });
44
+ return kmsId;
45
+ }
46
+ /**
47
+ * Gets public key by kmsKeyId
48
+ *
49
+ * @param {KmsKeyId} keyId - key identifier
50
+ */
51
+ async publicKey(keyId) {
52
+ const privateKeyHex = await this.privateKey(keyId);
53
+ const publicKey = secp256k1.getPublicKey(privateKeyHex, false); // 04 + x + y (uncompressed key)
54
+ return bytesToHex(publicKey);
55
+ }
56
+ /**
57
+ * Signs the given data using the private key associated with the specified key identifier.
58
+ * @param keyId - The key identifier to use for signing.
59
+ * @param data - The data to sign.
60
+ * @param opts - Signing options, such as the algorithm to use.
61
+ * @returns A Promise that resolves to the signature as a Uint8Array.
62
+ */
63
+ async sign(keyId, data, opts = { alg: 'ES256K' }) {
64
+ const privateKeyHex = await this.privateKey(keyId);
65
+ const signatureBase64 = await ES256KSigner(hexToBytes(privateKeyHex), opts.alg === 'ES256K-R')(data);
66
+ if (typeof signatureBase64 !== 'string') {
67
+ throw new Error('signatureBase64 must be a string');
68
+ }
69
+ return base64UrlToBytes(signatureBase64);
70
+ }
71
+ /**
72
+ * Verifies a signature for the given message and key identifier.
73
+ * @param message - The message to verify the signature against.
74
+ * @param signatureHex - The signature to verify, as a hexadecimal string.
75
+ * @param keyId - The key identifier to use for verification.
76
+ * @returns A Promise that resolves to a boolean indicating whether the signature is valid.
77
+ */
78
+ async verify(message, signatureHex, keyId) {
79
+ const publicKeyHex = await this.publicKey(keyId);
80
+ return secp256k1.verify(signatureHex, sha256(message), publicKeyHex);
81
+ }
82
+ async privateKey(keyId) {
83
+ return this._keyStore.get({ alias: keyId.id });
84
+ }
85
+ }
@@ -62,4 +62,19 @@ export class KMS {
62
62
  }
63
63
  return keyProvider.sign(keyId, data, opts);
64
64
  }
65
+ /**
66
+ * Verifies a signature against the provided data and key ID.
67
+ *
68
+ * @param data - The data to verify the signature against.
69
+ * @param signatureHex - The signature to verify, in hexadecimal format.
70
+ * @param keyId - The key ID to use for verification.
71
+ * @returns A promise that resolves to a boolean indicating whether the signature is valid.
72
+ */
73
+ verify(data, signatureHex, keyId) {
74
+ const keyProvider = this._registry.get(keyId.type);
75
+ if (!keyProvider) {
76
+ throw new Error(`keyProvider not found for: ${keyId.type}`);
77
+ }
78
+ return keyProvider.verify(data, signatureHex, keyId);
79
+ }
65
80
  }