@docknetwork/wallet-sdk-wasm 1.5.14 → 1.7.6

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 (146) hide show
  1. package/generate-docs.js +49 -0
  2. package/jsdoc.conf.json +29 -6
  3. package/lib/index.js +9 -1
  4. package/lib/index.mjs +9 -1
  5. package/lib/modules/network-manager.js +15 -12
  6. package/lib/modules/network-manager.mjs +15 -12
  7. package/lib/rpc-server.js +11 -1
  8. package/lib/rpc-server.mjs +11 -1
  9. package/lib/services/blockchain/cached-did-resolver.js +113 -0
  10. package/lib/services/blockchain/cached-did-resolver.mjs +109 -0
  11. package/lib/services/blockchain/index.js +11 -0
  12. package/lib/services/blockchain/index.mjs +11 -0
  13. package/lib/services/blockchain/service-rpc.js +12 -0
  14. package/lib/services/blockchain/service-rpc.mjs +12 -0
  15. package/lib/services/blockchain/service.js +161 -19
  16. package/lib/services/blockchain/service.mjs +162 -20
  17. package/lib/services/credential/bbs-revocation.js +11 -0
  18. package/lib/services/credential/bbs-revocation.mjs +11 -0
  19. package/lib/services/credential/bound-check.js +1 -1
  20. package/lib/services/credential/bound-check.mjs +1 -1
  21. package/lib/services/credential/config.js +4 -1
  22. package/lib/services/credential/config.mjs +4 -1
  23. package/lib/services/credential/delegatable-credentials.js +300 -0
  24. package/lib/services/credential/delegatable-credentials.mjs +263 -0
  25. package/lib/services/credential/index.js +53 -0
  26. package/lib/services/credential/index.mjs +18 -0
  27. package/lib/services/credential/pex-helpers.js +4 -4
  28. package/lib/services/credential/pex-helpers.mjs +4 -4
  29. package/lib/services/credential/sd-jwt.js +214 -0
  30. package/lib/services/credential/sd-jwt.mjs +200 -0
  31. package/lib/services/credential/service-rpc.js +9 -0
  32. package/lib/services/credential/service-rpc.mjs +9 -0
  33. package/lib/services/credential/service.js +324 -7
  34. package/lib/services/credential/service.mjs +324 -7
  35. package/lib/services/edv/index.js +1 -0
  36. package/lib/services/edv/index.mjs +1 -0
  37. package/lib/services/edv/service-rpc.js +23 -0
  38. package/lib/services/edv/service-rpc.mjs +23 -0
  39. package/lib/services/edv/service.js +226 -2
  40. package/lib/services/edv/service.mjs +223 -3
  41. package/lib/services/index.js +14 -0
  42. package/lib/services/index.mjs +14 -0
  43. package/lib/services/pex/config.js +4 -0
  44. package/lib/services/pex/config.mjs +4 -0
  45. package/lib/services/pex/service-rpc.js +4 -0
  46. package/lib/services/pex/service-rpc.mjs +4 -0
  47. package/lib/services/pex/service.js +7 -0
  48. package/lib/services/pex/service.mjs +7 -0
  49. package/lib/services/relay-service/service.js +124 -1
  50. package/lib/services/relay-service/service.mjs +124 -1
  51. package/lib/services/rpc-service-client.js +0 -3
  52. package/lib/services/rpc-service-client.mjs +0 -3
  53. package/lib/services/storage/index.js +19 -2
  54. package/lib/services/storage/index.mjs +24 -1
  55. package/lib/services/storage/service-rpc.js +7 -3
  56. package/lib/services/storage/service-rpc.mjs +7 -3
  57. package/lib/services/storage/service.js +4 -0
  58. package/lib/services/storage/service.mjs +4 -0
  59. package/lib/setup-nodejs.js +9 -1
  60. package/lib/setup-nodejs.mjs +9 -1
  61. package/lib/setup-tests.js +9 -1
  62. package/lib/setup-tests.mjs +9 -1
  63. package/lib/src/modules/event-manager.d.ts +0 -1
  64. package/lib/src/modules/event-manager.d.ts.map +1 -1
  65. package/lib/src/modules/network-manager.d.ts +2 -4
  66. package/lib/src/modules/network-manager.d.ts.map +1 -1
  67. package/lib/src/services/blockchain/cached-did-resolver.d.ts +28 -0
  68. package/lib/src/services/blockchain/cached-did-resolver.d.ts.map +1 -0
  69. package/lib/src/services/blockchain/cached-did-resolver.test.d.ts +2 -0
  70. package/lib/src/services/blockchain/cached-did-resolver.test.d.ts.map +1 -0
  71. package/lib/src/services/blockchain/configs.d.ts +1 -2
  72. package/lib/src/services/blockchain/configs.d.ts.map +1 -1
  73. package/lib/src/services/blockchain/service.d.ts +117 -19
  74. package/lib/src/services/blockchain/service.d.ts.map +1 -1
  75. package/lib/src/services/credential/bbs-revocation.d.ts +1 -1
  76. package/lib/src/services/credential/bbs-revocation.d.ts.map +1 -1
  77. package/lib/src/services/credential/bound-check.d.ts.map +1 -1
  78. package/lib/src/services/credential/config.d.ts.map +1 -1
  79. package/lib/src/services/credential/delegatable-credentials.d.ts +272 -0
  80. package/lib/src/services/credential/delegatable-credentials.d.ts.map +1 -0
  81. package/lib/src/services/credential/index.d.ts +4 -0
  82. package/lib/src/services/credential/index.d.ts.map +1 -1
  83. package/lib/src/services/credential/pex-helpers.d.ts +2 -2
  84. package/lib/src/services/credential/pex-helpers.d.ts.map +1 -1
  85. package/lib/src/services/credential/sd-jwt.test.d.ts +2 -0
  86. package/lib/src/services/credential/sd-jwt.test.d.ts.map +1 -0
  87. package/lib/src/services/credential/service.d.ts +274 -4
  88. package/lib/src/services/credential/service.d.ts.map +1 -1
  89. package/lib/src/services/dids/keypair-utils.d.ts +2 -2
  90. package/lib/src/services/dids/keypair-utils.d.ts.map +1 -1
  91. package/lib/src/services/dids/service.d.ts +35 -3
  92. package/lib/src/services/dids/service.d.ts.map +1 -1
  93. package/lib/src/services/edv/service.d.ts +201 -2
  94. package/lib/src/services/edv/service.d.ts.map +1 -1
  95. package/lib/src/services/pex/config.d.ts +1 -0
  96. package/lib/src/services/pex/config.d.ts.map +1 -1
  97. package/lib/src/services/pex/service.d.ts +1 -0
  98. package/lib/src/services/pex/service.d.ts.map +1 -1
  99. package/lib/src/services/relay-service/service.d.ts +148 -8
  100. package/lib/src/services/relay-service/service.d.ts.map +1 -1
  101. package/lib/src/services/rpc-service-client.d.ts +2 -2
  102. package/lib/src/services/rpc-service-client.d.ts.map +1 -1
  103. package/lib/src/services/storage/index.d.ts +1 -1
  104. package/lib/src/services/storage/index.d.ts.map +1 -1
  105. package/lib/src/services/storage/service-rpc.d.ts +9 -0
  106. package/lib/src/services/storage/service-rpc.d.ts.map +1 -0
  107. package/lib/src/services/storage/service.d.ts +1 -0
  108. package/lib/src/services/storage/service.d.ts.map +1 -1
  109. package/lib/src/services/util-crypto/service.d.ts +2 -2
  110. package/lib/src/services/util-crypto/service.d.ts.map +1 -1
  111. package/lib/tsconfig.tsbuildinfo +1 -1
  112. package/lib/wallet/rpc-storage-interface.js +13 -3
  113. package/lib/wallet/rpc-storage-interface.mjs +11 -1
  114. package/lib/wallet/rpc-storage-wallet.js +10 -0
  115. package/lib/wallet/rpc-storage-wallet.mjs +10 -0
  116. package/package.json +29 -16
  117. package/rollup.config.mjs +5 -3
  118. package/src/globals.d.ts +3 -0
  119. package/src/modules/network-manager.ts +15 -14
  120. package/src/services/blockchain/cached-did-resolver.test.ts +288 -0
  121. package/src/services/blockchain/cached-did-resolver.ts +126 -0
  122. package/src/services/blockchain/configs.ts +1 -2
  123. package/src/services/blockchain/service-rpc.js +12 -0
  124. package/src/services/blockchain/service.ts +167 -20
  125. package/src/services/credential/bound-check.ts +1 -1
  126. package/src/services/credential/config.ts +7 -1
  127. package/src/services/credential/delegatable-credentials.ts +409 -0
  128. package/src/services/credential/index.ts +16 -0
  129. package/src/services/credential/pex-helpers.js +4 -4
  130. package/src/services/credential/pex-helpers.test.js +2 -2
  131. package/src/services/credential/sd-jwt.test.ts +718 -0
  132. package/src/services/credential/sd-jwt.ts +231 -0
  133. package/src/services/credential/service-rpc.js +9 -0
  134. package/src/services/credential/service.ts +328 -7
  135. package/src/services/edv/index.test.js +229 -0
  136. package/src/services/edv/service-rpc.js +23 -0
  137. package/src/services/edv/service.ts +272 -1
  138. package/src/services/pex/config.ts +4 -0
  139. package/src/services/pex/service-rpc.js +4 -0
  140. package/src/services/pex/service.ts +13 -0
  141. package/src/services/pex/tests/pex-service.test.js +210 -0
  142. package/src/services/relay-service/service.ts +130 -1
  143. package/src/services/rpc-service-client.js +0 -3
  144. package/src/services/storage/index.js +15 -1
  145. package/src/services/storage/service-rpc.js +7 -3
  146. package/src/services/storage/service.ts +5 -0
@@ -47,5 +47,234 @@ describe('EDVService', () => {
47
47
  expect(JSON.stringify(agreementKey)).toBe(derivedTestAgreementKey);
48
48
  });
49
49
  });
50
+
51
+ describe('deriveBiometricKey', () => {
52
+ it('should derive a key from biometric data', () => {
53
+ const biometricData = Buffer.from('mock-biometric-data');
54
+ const identifier = 'user@example.com';
55
+
56
+ const key = service.deriveBiometricKey(biometricData, identifier);
57
+
58
+ expect(key).toBeDefined();
59
+ expect(Buffer.isBuffer(key)).toBe(true);
60
+ expect(key.length).toBe(32); // HKDF_LENGTH
61
+ });
62
+
63
+ it('should produce consistent keys for same inputs', () => {
64
+ const biometricData = Buffer.from('mock-biometric-data');
65
+ const identifier = 'user@example.com';
66
+
67
+ const key1 = service.deriveBiometricKey(biometricData, identifier);
68
+ const key2 = service.deriveBiometricKey(biometricData, identifier);
69
+
70
+ expect(key1.equals(key2)).toBe(true);
71
+ });
72
+
73
+ it('should produce different keys for different identifiers', () => {
74
+ const biometricData = Buffer.from('mock-biometric-data');
75
+ const identifier1 = 'user1@example.com';
76
+ const identifier2 = 'user2@example.com';
77
+
78
+ const key1 = service.deriveBiometricKey(biometricData, identifier1);
79
+ const key2 = service.deriveBiometricKey(biometricData, identifier2);
80
+
81
+ expect(key1.equals(key2)).toBe(false);
82
+ });
83
+
84
+ it('should produce different keys for different biometric data', () => {
85
+ const biometricData1 = Buffer.from('mock-biometric-data-1');
86
+ const biometricData2 = Buffer.from('mock-biometric-data-2');
87
+ const identifier = 'user@example.com';
88
+
89
+ const key1 = service.deriveBiometricKey(biometricData1, identifier);
90
+ const key2 = service.deriveBiometricKey(biometricData2, identifier);
91
+
92
+ expect(key1.equals(key2)).toBe(false);
93
+ });
94
+ });
95
+
96
+ describe('deriveBiometricEncryptionKey', () => {
97
+ it('should derive encryption key and IV', async () => {
98
+ const biometricData = Buffer.from('mock-biometric-data');
99
+ const identifier = 'user@example.com';
100
+
101
+ const result = await service.deriveBiometricEncryptionKey(
102
+ biometricData,
103
+ identifier,
104
+ );
105
+
106
+ expect(result).toBeDefined();
107
+ expect(result.key).toBeDefined();
108
+ expect(result.iv).toBeDefined();
109
+ expect(Buffer.isBuffer(result.key)).toBe(true);
110
+ expect(Buffer.isBuffer(result.iv)).toBe(true);
111
+ expect(result.key.length).toBe(32); // HKDF_LENGTH
112
+ expect(result.iv.length).toBe(16); // AES-GCM IV length
113
+ });
114
+
115
+ it('should produce consistent keys but different IVs for same inputs', async () => {
116
+ const biometricData = Buffer.from('mock-biometric-data');
117
+ const identifier = 'user@example.com';
118
+
119
+ const result1 = await service.deriveBiometricEncryptionKey(
120
+ biometricData,
121
+ identifier,
122
+ );
123
+ const result2 = await service.deriveBiometricEncryptionKey(
124
+ biometricData,
125
+ identifier,
126
+ );
127
+
128
+ expect(result1.key.equals(result2.key)).toBe(true);
129
+ // IVs should be different (random)
130
+ expect(result1.iv.equals(result2.iv)).toBe(false);
131
+ });
132
+ });
133
+
134
+ describe('encryptMasterKey and decryptMasterKey', () => {
135
+ it('should encrypt and decrypt master key successfully', async () => {
136
+ const masterKey = new Uint8Array(32).fill(42);
137
+ const encryptionKey = Buffer.from(new Uint8Array(32).fill(1));
138
+ const iv = Buffer.from(new Uint8Array(16).fill(2));
139
+
140
+ const encrypted = await service.encryptMasterKey(
141
+ masterKey,
142
+ encryptionKey,
143
+ iv,
144
+ );
145
+ expect(encrypted).toBeDefined();
146
+ expect(encrypted instanceof Uint8Array).toBe(true);
147
+ expect(encrypted.length).toBeGreaterThan(0);
148
+
149
+ const decrypted = await service.decryptMasterKey(
150
+ encrypted,
151
+ encryptionKey,
152
+ iv,
153
+ );
154
+ expect(decrypted).toBeDefined();
155
+ expect(decrypted instanceof Uint8Array).toBe(true);
156
+ expect(new Uint8Array(decrypted)).toEqual(masterKey);
157
+ });
158
+
159
+ it('should fail to decrypt with wrong key', async () => {
160
+ const masterKey = new Uint8Array(32).fill(42);
161
+ const encryptionKey = Buffer.from(new Uint8Array(32).fill(1));
162
+ const wrongKey = Buffer.from(new Uint8Array(32).fill(99));
163
+ const iv = Buffer.from(new Uint8Array(16).fill(2));
164
+
165
+ const encrypted = await service.encryptMasterKey(
166
+ masterKey,
167
+ encryptionKey,
168
+ iv,
169
+ );
170
+
171
+ await expect(
172
+ service.decryptMasterKey(encrypted, wrongKey, iv),
173
+ ).rejects.toThrow('Decryption failed: Invalid key or corrupted data');
174
+ });
175
+
176
+ it('should fail to decrypt with wrong IV', async () => {
177
+ const masterKey = new Uint8Array(32).fill(42);
178
+ const encryptionKey = Buffer.from(new Uint8Array(32).fill(1));
179
+ const iv = Buffer.from(new Uint8Array(16).fill(2));
180
+ const wrongIv = Buffer.from(new Uint8Array(16).fill(99));
181
+
182
+ const encrypted = await service.encryptMasterKey(
183
+ masterKey,
184
+ encryptionKey,
185
+ iv,
186
+ );
187
+
188
+ await expect(
189
+ service.decryptMasterKey(encrypted, encryptionKey, wrongIv),
190
+ ).rejects.toThrow('Decryption failed: Invalid key or corrupted data');
191
+ });
192
+
193
+ it('should produce different ciphertext for same plaintext with different IVs', async () => {
194
+ const masterKey = new Uint8Array(32).fill(42);
195
+ const encryptionKey = Buffer.from(new Uint8Array(32).fill(1));
196
+ const iv1 = Buffer.from(new Uint8Array(16).fill(2));
197
+ const iv2 = Buffer.from(new Uint8Array(16).fill(3));
198
+
199
+ const encrypted1 = await service.encryptMasterKey(
200
+ masterKey,
201
+ encryptionKey,
202
+ iv1,
203
+ );
204
+ const encrypted2 = await service.encryptMasterKey(
205
+ masterKey,
206
+ encryptionKey,
207
+ iv2,
208
+ );
209
+
210
+ expect(encrypted1).not.toEqual(encrypted2);
211
+ });
212
+
213
+ it('should handle empty master key', async () => {
214
+ const masterKey = new Uint8Array(0);
215
+ const encryptionKey = Buffer.from(new Uint8Array(32).fill(1));
216
+ const iv = Buffer.from(new Uint8Array(16).fill(2));
217
+
218
+ const encrypted = await service.encryptMasterKey(
219
+ masterKey,
220
+ encryptionKey,
221
+ iv,
222
+ );
223
+ const decrypted = await service.decryptMasterKey(
224
+ encrypted,
225
+ encryptionKey,
226
+ iv,
227
+ );
228
+
229
+ expect(new Uint8Array(decrypted)).toEqual(masterKey);
230
+ });
231
+ });
232
+
233
+ describe('integration: biometric encryption workflow', () => {
234
+ it('should complete full encryption workflow', async () => {
235
+ const biometricData = Buffer.from('mock-biometric-data');
236
+ const identifier = 'user@example.com';
237
+ const masterKey = new Uint8Array(32).fill(123);
238
+
239
+ // Derive encryption key and IV from biometric data
240
+ const {key, iv} = await service.deriveBiometricEncryptionKey(
241
+ biometricData,
242
+ identifier,
243
+ );
244
+
245
+ // Encrypt master key
246
+ const encrypted = await service.encryptMasterKey(masterKey, key, iv);
247
+
248
+ // Decrypt master key
249
+ const decrypted = await service.decryptMasterKey(encrypted, key, iv);
250
+
251
+ // Verify decrypted matches original
252
+ expect(new Uint8Array(decrypted)).toEqual(masterKey);
253
+ });
254
+
255
+ it('should fail workflow with different biometric data', async () => {
256
+ const biometricData1 = Buffer.from('mock-biometric-data-1');
257
+ const biometricData2 = Buffer.from('mock-biometric-data-2');
258
+ const identifier = 'user@example.com';
259
+ const masterKey = new Uint8Array(32).fill(123);
260
+
261
+ // Encrypt with first biometric data
262
+ const {key: key1, iv} = await service.deriveBiometricEncryptionKey(
263
+ biometricData1,
264
+ identifier,
265
+ );
266
+ const encrypted = await service.encryptMasterKey(masterKey, key1, iv);
267
+
268
+ // Try to decrypt with second biometric data (should fail)
269
+ const {key: key2} = await service.deriveBiometricEncryptionKey(
270
+ biometricData2,
271
+ identifier,
272
+ );
273
+
274
+ await expect(
275
+ service.decryptMasterKey(encrypted, key2, iv),
276
+ ).rejects.toThrow('Decryption failed: Invalid key or corrupted data');
277
+ });
278
+ });
50
279
  });
51
280
  });
@@ -38,4 +38,27 @@ export class EDVServiceRpc extends RpcService {
38
38
  delete(params: any) {
39
39
  return this.call('delete', params);
40
40
  }
41
+
42
+ deriveBiometricKey(biometricData: Buffer, identifier: string) {
43
+ return this.call('deriveBiometricKey', {biometricData, identifier});
44
+ }
45
+
46
+ deriveBiometricEncryptionKey(biometricData: Buffer, identifier: string) {
47
+ return this.call('deriveBiometricEncryptionKey', {
48
+ biometricData,
49
+ identifier,
50
+ });
51
+ }
52
+
53
+ encryptMasterKey(masterKey: Uint8Array, encryptionKey: Buffer, iv: Buffer) {
54
+ return this.call('encryptMasterKey', {masterKey, encryptionKey, iv});
55
+ }
56
+
57
+ decryptMasterKey(
58
+ encryptedKey: Uint8Array,
59
+ decryptionKey: Buffer,
60
+ iv: Buffer,
61
+ ) {
62
+ return this.call('decryptMasterKey', {encryptedKey, decryptionKey, iv});
63
+ }
41
64
  }
@@ -1,4 +1,12 @@
1
1
  // @ts-nocheck
2
+
3
+ /**
4
+ * @module edv-service
5
+ * @description Encrypted Data Vault (EDV) service for the Wallet SDK.
6
+ * This module provides secure, encrypted storage functionality using EDV protocol,
7
+ * enabling privacy-preserving data storage with client-side encryption.
8
+ */
9
+
2
10
  import {InitializeEDVParams, serviceName} from './configs';
3
11
  import EDVHTTPStorageInterface from '@docknetwork/universal-wallet/storage/edv-http-storage';
4
12
  import HMAC from './hmac';
@@ -9,9 +17,17 @@ import {getKeypairFromDoc} from '@docknetwork/universal-wallet/methods/keypairs'
9
17
  import {logger} from '@docknetwork/wallet-sdk-data-store/src/logger';
10
18
  import {didService} from '@docknetwork/wallet-sdk-wasm/src/services/dids/service';
11
19
  import {Ed25519Keypair} from '@docknetwork/credential-sdk/keypairs';
20
+ import hkdf from 'futoin-hkdf';
21
+ import crypto from '@docknetwork/universal-wallet/crypto';
22
+
23
+ export const HKDF_LENGTH = 32;
24
+ export const HKDF_HASH = 'SHA-256';
12
25
 
13
26
  /**
14
- * EDVService
27
+ * Service class for managing Encrypted Data Vaults
28
+ * @class
29
+ * @description Provides methods for creating, managing, and interacting with
30
+ * encrypted data vaults for secure storage of sensitive wallet data
15
31
  */
16
32
  export class EDVService {
17
33
  storageInterface: EDVHTTPStorageInterface;
@@ -28,12 +44,39 @@ export class EDVService {
28
44
  EDVService.prototype.update,
29
45
  EDVService.prototype.insert,
30
46
  EDVService.prototype.delete,
47
+ EDVService.prototype.deriveBiometricKey,
48
+ EDVService.prototype.deriveBiometricEncryptionKey,
49
+ EDVService.prototype.encryptMasterKey,
50
+ EDVService.prototype.decryptMasterKey,
31
51
  ];
32
52
 
53
+ /**
54
+ * Creates a new EDVService instance
55
+ * @constructor
56
+ */
33
57
  constructor() {
34
58
  this.name = serviceName;
35
59
  }
36
60
 
61
+ /**
62
+ * Initializes the EDV service with encryption keys and connection parameters
63
+ * @param {InitializeEDVParams} params - Initialization parameters
64
+ * @param {Object} params.hmacKey - HMAC key for document indexing
65
+ * @param {Object} params.agreementKey - Key agreement key for encryption
66
+ * @param {Object} params.verificationKey - Verification key for authentication
67
+ * @param {string} params.edvUrl - URL of the EDV server
68
+ * @param {string} params.authKey - Authentication key for the EDV server
69
+ * @returns {Promise<void>}
70
+ * @throws {Error} If unable to create or connect to EDV
71
+ * @example
72
+ * await edvService.initialize({
73
+ * hmacKey: hmacKeyData,
74
+ * agreementKey: agreementKeyData,
75
+ * verificationKey: verificationKeyData,
76
+ * edvUrl: 'https://edv.example.com',
77
+ * authKey: 'auth-token-123'
78
+ * });
79
+ */
37
80
  async initialize({
38
81
  hmacKey,
39
82
  agreementKey,
@@ -95,6 +138,21 @@ export class EDVService {
95
138
  });
96
139
  }
97
140
 
141
+ /**
142
+ * Generates new cryptographic keys for EDV operations
143
+ * @returns {Promise<Object>} Generated keys
144
+ * @returns {Object} returns.verificationKey - Ed25519 verification key for authentication
145
+ * @returns {Object} returns.agreementKey - X25519 key agreement key for encryption
146
+ * @returns {Object} returns.hmacKey - HMAC key for indexing
147
+ * @example
148
+ * const keys = await edvService.generateKeys();
149
+ * // Use keys for EDV initialization
150
+ * await edvService.initialize({
151
+ * ...keys,
152
+ * edvUrl: 'https://edv.example.com',
153
+ * authKey: 'auth-token'
154
+ * });
155
+ */
98
156
  async generateKeys() {
99
157
  const keyPair = await didService.generateKeyDoc({});
100
158
 
@@ -111,6 +169,17 @@ export class EDVService {
111
169
  return {verificationKey, agreementKey, hmacKey};
112
170
  }
113
171
 
172
+ /**
173
+ * Derives cryptographic keys from a master key
174
+ * @param {Uint8Array} masterKey - Master key for derivation
175
+ * @returns {Promise<Object>} Derived keys
176
+ * @returns {Object} returns.verificationKey - Derived Ed25519 verification key
177
+ * @returns {Object} returns.agreementKey - Derived X25519 key agreement key
178
+ * @returns {Object} returns.hmacKey - Derived HMAC key
179
+ * @example
180
+ * const masterKey = new Uint8Array(32); // Your master key
181
+ * const keys = await edvService.deriveKeys(masterKey);
182
+ */
114
183
  async deriveKeys(masterKey: Uint8Array) {
115
184
  const {keyPair: pair} = new Ed25519Keypair(masterKey, 'seed');
116
185
 
@@ -126,18 +195,66 @@ export class EDVService {
126
195
  return { verificationKey, agreementKey, hmacKey };
127
196
  }
128
197
 
198
+ /**
199
+ * Gets the controller identifier for the current EDV
200
+ * @returns {Promise<string>} The controller DID or identifier
201
+ * @example
202
+ * const controller = await edvService.getController();
203
+ * console.log('EDV Controller:', controller);
204
+ */
129
205
  async getController() {
130
206
  return this.controller;
131
207
  }
132
208
 
209
+ /**
210
+ * Finds documents in the EDV based on query parameters
211
+ * @param {Object} params - Query parameters
212
+ * @param {Object} [params.equals] - Equality-based query conditions
213
+ * @param {boolean} [params.has] - Existence-based query conditions
214
+ * @param {number} [params.limit] - Maximum number of results
215
+ * @returns {Promise<Array>} Array of matching documents
216
+ * @example
217
+ * const documents = await edvService.find({
218
+ * equals: { 'content.type': 'VerifiableCredential' },
219
+ * limit: 10
220
+ * });
221
+ */
133
222
  find(params: any) {
134
223
  return this.storageInterface.find(params);
135
224
  }
136
225
 
226
+ /**
227
+ * Updates a document in the EDV
228
+ * @param {Object} params - Update parameters
229
+ * @param {string} params.id - Document ID to update
230
+ * @param {Object} params.content - New document content
231
+ * @returns {Promise<Object>} Updated document
232
+ * @example
233
+ * const updated = await edvService.update({
234
+ * id: 'doc-123',
235
+ * content: { ...existingContent, updated: true }
236
+ * });
237
+ */
137
238
  update(params: any) {
138
239
  return this.storageInterface.update(params);
139
240
  }
140
241
 
242
+ /**
243
+ * Inserts a new document into the EDV
244
+ * @param {Object} params - Insert parameters
245
+ * @param {string} params.id - Document ID
246
+ * @param {Object} params.content - Document content to store
247
+ * @returns {Promise<Object>} The inserted document
248
+ * @throws {Error} If insertion fails
249
+ * @example
250
+ * const document = await edvService.insert({
251
+ * id: 'doc-456',
252
+ * content: {
253
+ * type: 'VerifiableCredential',
254
+ * data: credentialData
255
+ * }
256
+ * });
257
+ */
141
258
  insert(params: any) {
142
259
  this.insertQueue = this.insertQueue.then(() => {
143
260
  return this.storageInterface.insert(params).catch(error => {
@@ -148,9 +265,163 @@ export class EDVService {
148
265
  return this.insertQueue;
149
266
  }
150
267
 
268
+ /**
269
+ * Deletes a document from the EDV
270
+ * @param {Object} params - Deletion parameters
271
+ * @param {string} params.id - Document ID to delete
272
+ * @returns {Promise<boolean>} True if deletion successful
273
+ * @example
274
+ * const deleted = await edvService.delete({
275
+ * id: 'doc-123'
276
+ * });
277
+ */
151
278
  delete(params: any) {
152
279
  return this.storageInterface.delete(params);
153
280
  }
281
+
282
+ /**
283
+ * Derives a key from biometric data using HKDF
284
+ * @param {Buffer} biometricData - Biometric data from provider
285
+ * @param {string} identifier - User's identifier as salt (email, phone number, etc.)
286
+ * @returns {Buffer} Derived key
287
+ * @example
288
+ * const key = edvService.deriveBiometricKey(biometricData, 'user@example.com');
289
+ */
290
+ deriveBiometricKey(biometricData: Buffer, identifier: string): Buffer {
291
+ const salt = identifier;
292
+ return hkdf(biometricData, HKDF_LENGTH, { salt, hash: HKDF_HASH });
293
+ }
294
+
295
+ /**
296
+ * Generates a key for encrypting/decrypting the master key
297
+ * @param {Buffer} biometricData - Biometric data from provider
298
+ * @param {string} identifier - User's identifier as salt (email, phone number, etc.)
299
+ * @returns {Promise<Object>} Encryption key and IV for AES encryption
300
+ * @returns {Buffer} returns.key - Encryption key
301
+ * @returns {Buffer} returns.iv - Initialization vector
302
+ * @example
303
+ * const { key, iv } = await edvService.deriveBiometricEncryptionKey(biometricData, 'user@example.com');
304
+ */
305
+ async deriveBiometricEncryptionKey(
306
+ biometricData: Buffer,
307
+ identifier: string
308
+ ): Promise<{ key: Buffer; iv: Buffer }> {
309
+ const key = this.deriveBiometricKey(biometricData, identifier);
310
+ const randomBytes = crypto.getRandomValues(new Uint8Array(16));
311
+ const iv = Buffer.from(randomBytes);
312
+
313
+ return {
314
+ key,
315
+ iv
316
+ };
317
+ }
318
+
319
+ /**
320
+ * Encrypts the master key using a key derived from biometric data
321
+ * @param {Uint8Array} masterKey - The CloudWalletVault master key to encrypt
322
+ * @param {Buffer} encryptionKey - Key derived from biometric data
323
+ * @param {Buffer} iv - Initialization vector
324
+ * @returns {Promise<Uint8Array>} Encrypted master key
325
+ * @example
326
+ * const encrypted = await edvService.encryptMasterKey(masterKey, encryptionKey, iv);
327
+ */
328
+ async encryptMasterKey(
329
+ masterKey: Uint8Array,
330
+ encryptionKey: Buffer,
331
+ iv: Buffer
332
+ ): Promise<Uint8Array> {
333
+ const keyData = new Uint8Array(encryptionKey);
334
+ const ivData = new Uint8Array(iv);
335
+
336
+ const key = await crypto.subtle.importKey(
337
+ 'raw',
338
+ keyData,
339
+ { name: 'AES-GCM' },
340
+ false,
341
+ ['encrypt']
342
+ );
343
+
344
+ const encryptedBuffer = await crypto.subtle.encrypt(
345
+ { name: 'AES-GCM', iv: ivData },
346
+ key,
347
+ masterKey
348
+ );
349
+
350
+ return new Uint8Array(encryptedBuffer);
351
+ }
352
+
353
+ /**
354
+ * Decrypts the master key using biometric-derived key
355
+ * @param {Uint8Array} encryptedKey - The encrypted master key
356
+ * @param {Buffer} decryptionKey - Key derived from biometric data
357
+ * @param {Buffer} iv - Initialization vector
358
+ * @returns {Promise<Uint8Array>} The decrypted master key
359
+ * @throws {Error} If decryption fails
360
+ * @example
361
+ * const masterKey = await edvService.decryptMasterKey(encryptedKey, decryptionKey, iv);
362
+ */
363
+ async decryptMasterKey(
364
+ encryptedKey: Uint8Array,
365
+ decryptionKey: Buffer,
366
+ iv: Buffer
367
+ ): Promise<Uint8Array> {
368
+ try {
369
+ const keyData = new Uint8Array(decryptionKey);
370
+ const ivData = new Uint8Array(iv);
371
+
372
+ const key = await crypto.subtle.importKey(
373
+ 'raw',
374
+ keyData,
375
+ { name: 'AES-GCM' },
376
+ false,
377
+ ['decrypt']
378
+ );
379
+
380
+ const decryptedBuffer = await crypto.subtle.decrypt(
381
+ { name: 'AES-GCM', iv: ivData },
382
+ key,
383
+ encryptedKey
384
+ );
385
+
386
+ return new Uint8Array(decryptedBuffer);
387
+ } catch (error) {
388
+ throw new Error('Decryption failed: Invalid key or corrupted data');
389
+ }
390
+ }
154
391
  }
155
392
 
393
+ /**
394
+ * Singleton instance of the EDV service
395
+ * @type {EDVService}
396
+ * @example
397
+ * import { edvService } from '@docknetwork/wallet-sdk-wasm/services/edv';
398
+ *
399
+ * // Generate keys and initialize
400
+ * const keys = await edvService.generateKeys();
401
+ * await edvService.initialize({
402
+ * ...keys,
403
+ * edvUrl: 'https://edv.example.com',
404
+ * authKey: 'auth-token'
405
+ * });
406
+ *
407
+ * // Store encrypted data
408
+ * await edvService.insert({
409
+ * id: 'credential-1',
410
+ * content: {
411
+ * type: 'VerifiableCredential',
412
+ * data: credentialData
413
+ * }
414
+ * });
415
+ *
416
+ * // Query encrypted data
417
+ * const credentials = await edvService.find({
418
+ * equals: { 'content.type': 'VerifiableCredential' }
419
+ * });
420
+ *
421
+ * // Update encrypted data
422
+ * await edvService.update({
423
+ * id: 'credential-1',
424
+ * content: updatedData
425
+ * });
426
+ */
156
427
  export const edvService: EDVService = new EDVService();
@@ -7,6 +7,10 @@ export const validation = {
7
7
  assert(params.credentials, 'credentials is required');
8
8
  assert(params.presentationDefinition, 'presentationDefinition is required');
9
9
  },
10
+ evaluateCredentials: (params: EvaluateCredentialsParams) => {
11
+ assert(params.credentials, 'credentials is required');
12
+ assert(params.presentationDefinition, 'presentationDefinition is required');
13
+ },
10
14
  evaluatePresentation: (params: EvaluatePresentationParams) => {
11
15
  assert(params.presentation, 'presentation is required');
12
16
  assert(params.presentationDefinition, 'presentationDefinition is required');
@@ -24,4 +24,8 @@ export class PEXServiceRPC extends RpcService {
24
24
  async presentationFrom(params: CreatePresentationParams) {
25
25
  return this.call('presentationFrom', params);
26
26
  }
27
+
28
+ async isCredentialSelectionValid(params: EvaluateCredentialsParams) {
29
+ return this.call('isCredentialSelectionValid', params);
30
+ }
27
31
  }
@@ -78,6 +78,7 @@ class PEXService {
78
78
  PEXService.prototype.filterCredentials,
79
79
  PEXService.prototype.evaluatePresentation,
80
80
  PEXService.prototype.presentationFrom,
81
+ PEXService.prototype.isCredentialSelectionValid,
81
82
  ];
82
83
 
83
84
  filterCredentials(params: FilterCredentialsParams) {
@@ -92,6 +93,18 @@ class PEXService {
92
93
  return result;
93
94
  }
94
95
 
96
+ isCredentialSelectionValid(params: EvaluateCredentialsParams) {
97
+ validation.evaluateCredentials(params);
98
+ const {credentials, presentationDefinition, holderDIDs} = params;
99
+ const result = pex.selectFrom(
100
+ removeOptionalAttribute(presentationDefinition),
101
+ credentials,
102
+ holderDIDs,
103
+ );
104
+
105
+ return result.errors.length === 0;
106
+ }
107
+
95
108
  evaluatePresentation(params: EvaluatePresentationParams) {
96
109
  validation.evaluatePresentation(params);
97
110
  const {presentation, presentationDefinition} = params;