@docknetwork/wallet-sdk-wasm 1.7.0 → 1.7.7-alpha.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.
- package/lib/index.js +1 -0
- package/lib/index.mjs +1 -0
- package/lib/modules/network-manager.js +15 -12
- package/lib/modules/network-manager.mjs +15 -12
- package/lib/rpc-server.js +1 -0
- package/lib/rpc-server.mjs +1 -0
- package/lib/services/blockchain/service.js +22 -9
- package/lib/services/blockchain/service.mjs +23 -10
- package/lib/services/credential/bound-check.js +1 -1
- package/lib/services/credential/bound-check.mjs +1 -1
- package/lib/services/credential/delegatable-credentials.js +300 -0
- package/lib/services/credential/delegatable-credentials.mjs +263 -0
- package/lib/services/credential/index.js +39 -0
- package/lib/services/credential/index.mjs +4 -0
- package/lib/services/credential/pex-helpers.js +4 -4
- package/lib/services/credential/pex-helpers.mjs +4 -4
- package/lib/services/edv/index.js +1 -0
- package/lib/services/edv/index.mjs +1 -0
- package/lib/services/edv/service-rpc.js +23 -0
- package/lib/services/edv/service-rpc.mjs +23 -0
- package/lib/services/edv/service.js +81 -1
- package/lib/services/edv/service.mjs +78 -2
- package/lib/services/index.js +1 -0
- package/lib/services/index.mjs +1 -0
- package/lib/services/pex/config.js +4 -0
- package/lib/services/pex/config.mjs +4 -0
- package/lib/services/pex/service-rpc.js +4 -0
- package/lib/services/pex/service-rpc.mjs +4 -0
- package/lib/services/pex/service.js +7 -0
- package/lib/services/pex/service.mjs +7 -0
- package/lib/setup-nodejs.js +1 -0
- package/lib/setup-nodejs.mjs +1 -0
- package/lib/setup-tests.js +1 -0
- package/lib/setup-tests.mjs +1 -0
- package/lib/src/modules/event-manager.d.ts +0 -1
- package/lib/src/modules/event-manager.d.ts.map +1 -1
- package/lib/src/modules/network-manager.d.ts +2 -4
- package/lib/src/modules/network-manager.d.ts.map +1 -1
- package/lib/src/services/blockchain/configs.d.ts +1 -2
- package/lib/src/services/blockchain/configs.d.ts.map +1 -1
- package/lib/src/services/blockchain/service.d.ts +4 -3
- package/lib/src/services/blockchain/service.d.ts.map +1 -1
- package/lib/src/services/credential/bbs-revocation.d.ts +1 -1
- package/lib/src/services/credential/bbs-revocation.d.ts.map +1 -1
- package/lib/src/services/credential/bound-check.d.ts.map +1 -1
- package/lib/src/services/credential/delegatable-credentials.d.ts +272 -0
- package/lib/src/services/credential/delegatable-credentials.d.ts.map +1 -0
- package/lib/src/services/credential/index.d.ts +1 -0
- package/lib/src/services/credential/index.d.ts.map +1 -1
- package/lib/src/services/credential/pex-helpers.d.ts +2 -2
- package/lib/src/services/credential/pex-helpers.d.ts.map +1 -1
- package/lib/src/services/dids/keypair-utils.d.ts +2 -2
- package/lib/src/services/dids/keypair-utils.d.ts.map +1 -1
- package/lib/src/services/dids/service.d.ts +35 -3
- package/lib/src/services/dids/service.d.ts.map +1 -1
- package/lib/src/services/edv/service.d.ts +50 -1
- package/lib/src/services/edv/service.d.ts.map +1 -1
- package/lib/src/services/pex/config.d.ts +1 -0
- package/lib/src/services/pex/config.d.ts.map +1 -1
- package/lib/src/services/pex/service.d.ts +1 -0
- package/lib/src/services/pex/service.d.ts.map +1 -1
- package/lib/src/services/relay-service/service.d.ts +19 -7
- package/lib/src/services/relay-service/service.d.ts.map +1 -1
- package/lib/src/services/storage/service.d.ts.map +1 -1
- package/lib/src/services/util-crypto/service.d.ts +2 -2
- package/lib/src/services/util-crypto/service.d.ts.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +36 -16
- package/rollup.config.mjs +5 -3
- package/src/globals.d.ts +3 -0
- package/src/modules/network-manager.ts +15 -14
- package/src/services/blockchain/configs.ts +1 -2
- package/src/services/blockchain/service.ts +26 -10
- package/src/services/credential/bound-check.ts +1 -1
- package/src/services/credential/delegatable-credentials.ts +409 -0
- package/src/services/credential/index.ts +16 -0
- package/src/services/credential/pex-helpers.js +4 -4
- package/src/services/credential/pex-helpers.test.js +2 -2
- package/src/services/edv/index.test.js +229 -0
- package/src/services/edv/service-rpc.js +23 -0
- package/src/services/edv/service.ts +119 -0
- package/src/services/pex/config.ts +4 -0
- package/src/services/pex/service-rpc.js +4 -0
- package/src/services/pex/service.ts +13 -0
- package/src/services/pex/tests/pex-service.test.js +210 -0
|
@@ -5,10 +5,10 @@ export const EPSILON_INT = 1;
|
|
|
5
5
|
|
|
6
6
|
export const MAX_DATE_PLACEHOLDER = 884541351600000;
|
|
7
7
|
export const MIN_DATE_PLACEHOLDER = -17592186044415;
|
|
8
|
-
export const MAX_INTEGER =
|
|
9
|
-
export const MIN_INTEGER =
|
|
10
|
-
export const MAX_NUMBER =
|
|
11
|
-
export const MIN_NUMBER =
|
|
8
|
+
export const MAX_INTEGER = Number.MAX_SAFE_INTEGER;
|
|
9
|
+
export const MIN_INTEGER = Number.MIN_SAFE_INTEGER;
|
|
10
|
+
export const MAX_NUMBER = Number.MAX_SAFE_INTEGER;
|
|
11
|
+
export const MIN_NUMBER = Number.MIN_SAFE_INTEGER;
|
|
12
12
|
|
|
13
13
|
/*
|
|
14
14
|
PEX Filter rules:
|
|
@@ -302,7 +302,7 @@ describe('pex helpers', () => {
|
|
|
302
302
|
{
|
|
303
303
|
attributeName: 'credentialSubject.age',
|
|
304
304
|
min: 0,
|
|
305
|
-
max:
|
|
305
|
+
max: Number.MAX_SAFE_INTEGER,
|
|
306
306
|
proofRequestMax: undefined,
|
|
307
307
|
proofRequestMin: 0,
|
|
308
308
|
format: undefined,
|
|
@@ -357,7 +357,7 @@ describe('pex helpers', () => {
|
|
|
357
357
|
{
|
|
358
358
|
attributeName: 'credentialSubject.age',
|
|
359
359
|
min: 0,
|
|
360
|
-
max:
|
|
360
|
+
max: Number.MAX_SAFE_INTEGER,
|
|
361
361
|
proofRequestMax: undefined,
|
|
362
362
|
proofRequestMin: 0,
|
|
363
363
|
format: undefined,
|
|
@@ -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
|
}
|
|
@@ -17,6 +17,11 @@ import {getKeypairFromDoc} from '@docknetwork/universal-wallet/methods/keypairs'
|
|
|
17
17
|
import {logger} from '@docknetwork/wallet-sdk-data-store/src/logger';
|
|
18
18
|
import {didService} from '@docknetwork/wallet-sdk-wasm/src/services/dids/service';
|
|
19
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';
|
|
20
25
|
|
|
21
26
|
/**
|
|
22
27
|
* Service class for managing Encrypted Data Vaults
|
|
@@ -39,6 +44,10 @@ export class EDVService {
|
|
|
39
44
|
EDVService.prototype.update,
|
|
40
45
|
EDVService.prototype.insert,
|
|
41
46
|
EDVService.prototype.delete,
|
|
47
|
+
EDVService.prototype.deriveBiometricKey,
|
|
48
|
+
EDVService.prototype.deriveBiometricEncryptionKey,
|
|
49
|
+
EDVService.prototype.encryptMasterKey,
|
|
50
|
+
EDVService.prototype.decryptMasterKey,
|
|
42
51
|
];
|
|
43
52
|
|
|
44
53
|
/**
|
|
@@ -269,6 +278,116 @@ export class EDVService {
|
|
|
269
278
|
delete(params: any) {
|
|
270
279
|
return this.storageInterface.delete(params);
|
|
271
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
|
+
}
|
|
272
391
|
}
|
|
273
392
|
|
|
274
393
|
/**
|
|
@@ -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;
|