@didcid/keymaster 0.2.0 → 0.3.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.
@@ -8,41 +8,6 @@ var db_typeGuards = require('./db/typeGuards.cjs');
8
8
  require('crypto');
9
9
  var encryption = require('./encryption.cjs');
10
10
 
11
- class ArchonError extends Error {
12
- type;
13
- detail;
14
- constructor(type, detail) {
15
- const message = detail ? `${type}: ${detail}` : type;
16
- super(message);
17
- this.type = type;
18
- this.detail = detail;
19
- }
20
- }
21
- class InvalidDIDError extends ArchonError {
22
- static type = 'Invalid DID';
23
- constructor(detail) {
24
- super(InvalidDIDError.type, detail);
25
- }
26
- }
27
- class InvalidParameterError extends ArchonError {
28
- static type = 'Invalid parameter';
29
- constructor(detail) {
30
- super(InvalidParameterError.type, detail);
31
- }
32
- }
33
- class KeymasterError extends ArchonError {
34
- static type = 'Keymaster';
35
- constructor(detail) {
36
- super(KeymasterError.type, detail);
37
- }
38
- }
39
- class UnknownIDError extends ArchonError {
40
- static type = 'Unknown ID';
41
- constructor(detail) {
42
- super(UnknownIDError.type, detail);
43
- }
44
- }
45
-
46
11
  function equals$1(aa, bb) {
47
12
  if (aa === bb) {
48
13
  return true;
@@ -443,6 +408,66 @@ function rfc4648({ name, prefix, bitsPerChar, alphabet }) {
443
408
  });
444
409
  }
445
410
 
411
+ rfc4648({
412
+ prefix: 'm',
413
+ name: 'base64',
414
+ alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
415
+ bitsPerChar: 6
416
+ });
417
+ rfc4648({
418
+ prefix: 'M',
419
+ name: 'base64pad',
420
+ alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
421
+ bitsPerChar: 6
422
+ });
423
+ const base64url = rfc4648({
424
+ prefix: 'u',
425
+ name: 'base64url',
426
+ alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_',
427
+ bitsPerChar: 6
428
+ });
429
+ rfc4648({
430
+ prefix: 'U',
431
+ name: 'base64urlpad',
432
+ alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=',
433
+ bitsPerChar: 6
434
+ });
435
+
436
+ class ArchonError extends Error {
437
+ type;
438
+ detail;
439
+ constructor(type, detail) {
440
+ const message = detail ? `${type}: ${detail}` : type;
441
+ super(message);
442
+ this.type = type;
443
+ this.detail = detail;
444
+ }
445
+ }
446
+ class InvalidDIDError extends ArchonError {
447
+ static type = 'Invalid DID';
448
+ constructor(detail) {
449
+ super(InvalidDIDError.type, detail);
450
+ }
451
+ }
452
+ class InvalidParameterError extends ArchonError {
453
+ static type = 'Invalid parameter';
454
+ constructor(detail) {
455
+ super(InvalidParameterError.type, detail);
456
+ }
457
+ }
458
+ class KeymasterError extends ArchonError {
459
+ static type = 'Keymaster';
460
+ constructor(detail) {
461
+ super(KeymasterError.type, detail);
462
+ }
463
+ }
464
+ class UnknownIDError extends ArchonError {
465
+ static type = 'Unknown ID';
466
+ constructor(detail) {
467
+ super(UnknownIDError.type, detail);
468
+ }
469
+ }
470
+
446
471
  const base32 = rfc4648({
447
472
  prefix: 'b',
448
473
  name: 'base32',
@@ -1057,6 +1082,14 @@ function isValidDID(did) {
1057
1082
  return isValidCID(suffix);
1058
1083
  }
1059
1084
 
1085
+ function hexToBase64url(hex) {
1086
+ const bytes = Buffer.from(hex, 'hex');
1087
+ return base64url.baseEncode(bytes);
1088
+ }
1089
+ function base64urlToHex(b64) {
1090
+ const bytes = base64url.baseDecode(b64);
1091
+ return Buffer.from(bytes).toString('hex');
1092
+ }
1060
1093
  const DefaultSchema = {
1061
1094
  "$schema": "http://json-schema.org/draft-07/schema#",
1062
1095
  "type": "object",
@@ -1354,13 +1387,15 @@ class Keymaster {
1354
1387
  publicJwk: keypair.publicJwk,
1355
1388
  };
1356
1389
  const msgHash = this.cipher.hashJSON(operation);
1357
- const signature = this.cipher.signHash(msgHash, keypair.privateJwk);
1390
+ const signatureHex = this.cipher.signHash(msgHash, keypair.privateJwk);
1358
1391
  const signed = {
1359
1392
  ...operation,
1360
- signature: {
1361
- signed: new Date(0).toISOString(),
1362
- hash: msgHash,
1363
- value: signature
1393
+ proof: {
1394
+ type: "EcdsaSecp256k1Signature2019",
1395
+ created: new Date(0).toISOString(),
1396
+ verificationMethod: "#key-1",
1397
+ proofPurpose: "authentication",
1398
+ proofValue: hexToBase64url(signatureHex),
1364
1399
  }
1365
1400
  };
1366
1401
  const did = await this.gatekeeper.createDID(signed);
@@ -1381,14 +1416,15 @@ class Keymaster {
1381
1416
  doc,
1382
1417
  };
1383
1418
  const msgHash = this.cipher.hashJSON(operation);
1384
- const signature = this.cipher.signHash(msgHash, keypair.privateJwk);
1419
+ const signatureHex = this.cipher.signHash(msgHash, keypair.privateJwk);
1385
1420
  const signed = {
1386
1421
  ...operation,
1387
- signature: {
1388
- signer: did,
1389
- signed: new Date().toISOString(),
1390
- hash: msgHash,
1391
- value: signature,
1422
+ proof: {
1423
+ type: "EcdsaSecp256k1Signature2019",
1424
+ created: new Date().toISOString(),
1425
+ verificationMethod: `${did}#key-1`,
1426
+ proofPurpose: "authentication",
1427
+ proofValue: hexToBase64url(signatureHex),
1392
1428
  }
1393
1429
  };
1394
1430
  return await this.gatekeeper.updateDID(signed);
@@ -1413,14 +1449,15 @@ class Keymaster {
1413
1449
  data: { backup: backup },
1414
1450
  };
1415
1451
  const msgHash = this.cipher.hashJSON(operation);
1416
- const signature = this.cipher.signHash(msgHash, keypair.privateJwk);
1452
+ const signatureHex = this.cipher.signHash(msgHash, keypair.privateJwk);
1417
1453
  const signed = {
1418
1454
  ...operation,
1419
- signature: {
1420
- signer: seedBank.didDocument?.id,
1421
- signed: new Date().toISOString(),
1422
- hash: msgHash,
1423
- value: signature,
1455
+ proof: {
1456
+ type: "EcdsaSecp256k1Signature2019",
1457
+ created: new Date().toISOString(),
1458
+ verificationMethod: `${seedBank.didDocument?.id}#key-1`,
1459
+ proofPurpose: "authentication",
1460
+ proofValue: hexToBase64url(signatureHex),
1424
1461
  }
1425
1462
  };
1426
1463
  const backupDID = await this.gatekeeper.createDID(signed);
@@ -1601,7 +1638,7 @@ class Keymaster {
1601
1638
  controller: id.did,
1602
1639
  data,
1603
1640
  };
1604
- const signed = await this.addSignature(operation, controller);
1641
+ const signed = await this.addProof(operation, controller, "authentication");
1605
1642
  const did = await this.gatekeeper.createDID(signed);
1606
1643
  // Keep assets that will be garbage-collected out of the owned list
1607
1644
  if (!validUntil) {
@@ -1790,7 +1827,7 @@ class Keymaster {
1790
1827
  throw new InvalidParameterError('did not encrypted JSON');
1791
1828
  }
1792
1829
  }
1793
- async addSignature(obj, controller) {
1830
+ async addProof(obj, controller, proofPurpose = "assertionMethod") {
1794
1831
  if (obj == null) {
1795
1832
  throw new InvalidParameterError('obj');
1796
1833
  }
@@ -1798,18 +1835,23 @@ class Keymaster {
1798
1835
  const id = await this.fetchIdInfo(controller);
1799
1836
  const keypair = await this.fetchKeyPair(controller);
1800
1837
  if (!keypair) {
1801
- throw new KeymasterError('addSignature: no keypair');
1838
+ throw new KeymasterError('addProof: no keypair');
1802
1839
  }
1840
+ // Get the key fragment from the DID document
1841
+ const doc = await this.resolveDID(id.did, { confirm: true });
1842
+ const keyFragment = doc.didDocument?.verificationMethod?.[0]?.id || '#key-1';
1803
1843
  try {
1804
1844
  const msgHash = this.cipher.hashJSON(obj);
1805
- const signature = this.cipher.signHash(msgHash, keypair.privateJwk);
1845
+ const signatureHex = this.cipher.signHash(msgHash, keypair.privateJwk);
1846
+ const proofValue = hexToBase64url(signatureHex);
1806
1847
  return {
1807
1848
  ...obj,
1808
- signature: {
1809
- signer: id.did,
1810
- signed: new Date().toISOString(),
1811
- hash: msgHash,
1812
- value: signature,
1849
+ proof: {
1850
+ type: "EcdsaSecp256k1Signature2019",
1851
+ created: new Date().toISOString(),
1852
+ verificationMethod: `${id.did}${keyFragment}`,
1853
+ proofPurpose,
1854
+ proofValue,
1813
1855
  }
1814
1856
  };
1815
1857
  }
@@ -1817,24 +1859,27 @@ class Keymaster {
1817
1859
  throw new InvalidParameterError('obj');
1818
1860
  }
1819
1861
  }
1820
- async verifySignature(obj) {
1821
- if (!obj?.signature) {
1862
+ async verifyProof(obj) {
1863
+ if (!obj?.proof) {
1822
1864
  return false;
1823
1865
  }
1824
- const { signature } = obj;
1825
- if (!signature.signer) {
1866
+ const { proof } = obj;
1867
+ if (proof.type !== "EcdsaSecp256k1Signature2019") {
1826
1868
  return false;
1827
1869
  }
1828
- const jsonCopy = JSON.parse(JSON.stringify(obj));
1829
- delete jsonCopy.signature;
1830
- const msgHash = this.cipher.hashJSON(jsonCopy);
1831
- if (signature.hash && signature.hash !== msgHash) {
1870
+ if (!proof.verificationMethod) {
1832
1871
  return false;
1833
1872
  }
1834
- const doc = await this.resolveDID(signature.signer, { versionTime: signature.signed });
1873
+ // Extract DID from verificationMethod
1874
+ const [signerDid] = proof.verificationMethod.split('#');
1875
+ const jsonCopy = JSON.parse(JSON.stringify(obj));
1876
+ delete jsonCopy.proof;
1877
+ const msgHash = this.cipher.hashJSON(jsonCopy);
1878
+ const doc = await this.resolveDID(signerDid, { versionTime: proof.created });
1835
1879
  const publicJwk = this.getPublicKeyJwk(doc);
1836
1880
  try {
1837
- return this.cipher.verifySig(msgHash, signature.value, publicJwk);
1881
+ const signatureHex = base64urlToHex(proof.proofValue);
1882
+ return this.cipher.verifySig(msgHash, signatureHex, publicJwk);
1838
1883
  }
1839
1884
  catch (error) {
1840
1885
  return false;
@@ -1863,7 +1908,7 @@ class Keymaster {
1863
1908
  else if (current.didDocumentRegistration?.type === 'asset') {
1864
1909
  controller = current.didDocument?.controller;
1865
1910
  }
1866
- const signed = await this.addSignature(operation, controller);
1911
+ const signed = await this.addProof(operation, controller, "authentication");
1867
1912
  return this.gatekeeper.updateDID(signed);
1868
1913
  }
1869
1914
  async revokeDID(id) {
@@ -1885,7 +1930,7 @@ class Keymaster {
1885
1930
  else if (current.didDocumentRegistration?.type === 'asset') {
1886
1931
  controller = current.didDocument?.controller;
1887
1932
  }
1888
- const signed = await this.addSignature(operation, controller);
1933
+ const signed = await this.addProof(operation, controller, "authentication");
1889
1934
  const ok = await this.gatekeeper.deleteDID(signed);
1890
1935
  if (ok && current.didDocument?.controller) {
1891
1936
  await this.removeFromOwned(did, current.didDocument.controller);
@@ -1965,9 +2010,13 @@ class Keymaster {
1965
2010
  }
1966
2011
  const controller = docs.didDocument?.controller || docs.didDocument?.id;
1967
2012
  const isOwned = await this.idInWallet(controller);
1968
- // Augment the DID document metadata with the DID ownership status
2013
+ // Convert versionSequence string to numeric version
2014
+ const versionSequence = docs.didDocumentMetadata?.versionSequence;
2015
+ const version = versionSequence ? parseInt(versionSequence, 10) : undefined;
2016
+ // Augment the DID document metadata with the DID ownership status and numeric version
1969
2017
  docs.didDocumentMetadata = {
1970
2018
  ...docs.didDocumentMetadata,
2019
+ version,
1971
2020
  isOwned,
1972
2021
  };
1973
2022
  return docs;
@@ -2086,13 +2135,15 @@ class Keymaster {
2086
2135
  publicJwk: keypair.publicJwk,
2087
2136
  };
2088
2137
  const msgHash = this.cipher.hashJSON(operation);
2089
- const signature = this.cipher.signHash(msgHash, keypair.privateJwk);
2138
+ const signatureHex = this.cipher.signHash(msgHash, keypair.privateJwk);
2090
2139
  const signed = {
2091
2140
  ...operation,
2092
- signature: {
2093
- signed: new Date().toISOString(),
2094
- hash: msgHash,
2095
- value: signature
2141
+ proof: {
2142
+ type: "EcdsaSecp256k1Signature2019",
2143
+ created: new Date().toISOString(),
2144
+ verificationMethod: "#key-1",
2145
+ proofPurpose: "authentication",
2146
+ proofValue: hexToBase64url(signatureHex),
2096
2147
  },
2097
2148
  };
2098
2149
  return signed;
@@ -2146,10 +2197,10 @@ class Keymaster {
2146
2197
  if (!registry) {
2147
2198
  throw new InvalidParameterError('no registry found for agent DID');
2148
2199
  }
2149
- const vaultDid = await this.createAsset({ backup: backup }, { registry, controller: name });
2200
+ const backupStoreDid = await this.createAsset({ backup: backup }, { registry, controller: name });
2150
2201
  if (doc.didDocumentData) {
2151
2202
  const currentData = doc.didDocumentData;
2152
- const updatedData = { ...currentData, vault: vaultDid };
2203
+ const updatedData = { ...currentData, backupStore: backupStoreDid };
2153
2204
  return this.updateDID(name, { didDocumentData: updatedData });
2154
2205
  }
2155
2206
  return false;
@@ -2159,14 +2210,14 @@ class Keymaster {
2159
2210
  const keypair = await this.hdKeyPair();
2160
2211
  const doc = await this.resolveDID(did);
2161
2212
  const docData = doc.didDocumentData;
2162
- if (!docData.vault) {
2163
- throw new InvalidDIDError('didDocumentData missing vault');
2213
+ if (!docData.backupStore) {
2214
+ throw new InvalidDIDError('didDocumentData missing backupStore');
2164
2215
  }
2165
- const vault = await this.resolveAsset(docData.vault);
2166
- if (typeof vault.backup !== 'string') {
2167
- throw new InvalidDIDError('backup not found in vault');
2216
+ const backupStore = await this.resolveAsset(docData.backupStore);
2217
+ if (typeof backupStore.backup !== 'string') {
2218
+ throw new InvalidDIDError('backup not found in backupStore');
2168
2219
  }
2169
- const backup = this.cipher.decryptMessage(keypair.publicJwk, keypair.privateJwk, vault.backup);
2220
+ const backup = this.cipher.decryptMessage(keypair.publicJwk, keypair.privateJwk, backupStore.backup);
2170
2221
  const data = JSON.parse(backup);
2171
2222
  await this.mutateWallet((wallet) => {
2172
2223
  if (wallet.ids[data.name]) {
@@ -2210,6 +2261,7 @@ class Keymaster {
2210
2261
  ...doc.didDocument,
2211
2262
  verificationMethod: [vmethod],
2212
2263
  authentication: [vmethod.id],
2264
+ assertionMethod: [vmethod.id],
2213
2265
  };
2214
2266
  ok = await this.updateDID(id.did, { didDocument: updatedDidDocument });
2215
2267
  if (!ok) {
@@ -2222,7 +2274,7 @@ class Keymaster {
2222
2274
  async listNames(options = {}) {
2223
2275
  const { includeIDs = false } = options;
2224
2276
  const wallet = await this.loadWallet();
2225
- const names = wallet.names || {};
2277
+ const names = { ...(wallet.names || {}) };
2226
2278
  if (includeIDs) {
2227
2279
  for (const [name, id] of Object.entries(wallet.ids || {})) {
2228
2280
  names[name] = id.did;
@@ -2260,42 +2312,60 @@ class Keymaster {
2260
2312
  const doc = await this.resolveDID(id);
2261
2313
  return doc.didDocumentRegistration?.type === 'agent';
2262
2314
  }
2263
- async bindCredential(schemaId, subjectId, options = {}) {
2264
- let { validFrom, validUntil, credential } = options;
2315
+ async bindCredential(subjectId, options = {}) {
2316
+ let { schema, validFrom, validUntil, claims, types } = options;
2265
2317
  if (!validFrom) {
2266
2318
  validFrom = new Date().toISOString();
2267
2319
  }
2268
2320
  const id = await this.fetchIdInfo();
2269
- const type = await this.lookupDID(schemaId);
2270
2321
  const subjectDID = await this.lookupDID(subjectId);
2271
- if (!credential) {
2272
- const schema = await this.getSchema(type);
2273
- credential = this.generateSchema(schema);
2274
- }
2275
- return {
2322
+ const vc = {
2276
2323
  "@context": [
2277
2324
  "https://www.w3.org/ns/credentials/v2",
2278
2325
  "https://www.w3.org/ns/credentials/examples/v2"
2279
2326
  ],
2280
- type: ["VerifiableCredential", type],
2327
+ type: ["VerifiableCredential", ...(types || [])],
2281
2328
  issuer: id.did,
2282
2329
  validFrom,
2283
2330
  validUntil,
2284
2331
  credentialSubject: {
2285
2332
  id: subjectDID,
2286
2333
  },
2287
- credential,
2288
2334
  };
2335
+ // If schema provided, add credentialSchema and generate claims from schema
2336
+ if (schema) {
2337
+ const schemaDID = await this.lookupDID(schema);
2338
+ const schemaDoc = await this.getSchema(schemaDID);
2339
+ if (!claims && schemaDoc) {
2340
+ claims = this.generateSchema(schemaDoc);
2341
+ }
2342
+ // If schema has $credentialTypes, add them to credential types (avoiding duplicates)
2343
+ if (schemaDoc?.$credentialTypes) {
2344
+ const newTypes = schemaDoc.$credentialTypes.filter(t => !vc.type.includes(t));
2345
+ vc.type.push(...newTypes);
2346
+ }
2347
+ vc.credentialSchema = {
2348
+ id: schemaDID,
2349
+ type: "JsonSchema",
2350
+ };
2351
+ }
2352
+ if (claims) {
2353
+ vc.credentialSubject = {
2354
+ id: subjectDID,
2355
+ ...claims,
2356
+ };
2357
+ }
2358
+ return vc;
2289
2359
  }
2290
2360
  async issueCredential(credential, options = {}) {
2291
2361
  const id = await this.fetchIdInfo();
2292
2362
  if (options.schema && options.subject) {
2293
- credential = await this.bindCredential(options.schema, options.subject, { credential, ...options });
2363
+ credential = await this.bindCredential(options.subject, { schema: options.schema, claims: options.claims, ...options });
2294
2364
  }
2295
2365
  if (credential.issuer !== id.did) {
2296
2366
  throw new InvalidParameterError('credential.issuer');
2297
2367
  }
2298
- const signed = await this.addSignature(credential);
2368
+ const signed = await this.addProof(credential);
2299
2369
  return this.encryptJSON(signed, credential.credentialSubject.id, { ...options, includeHash: true });
2300
2370
  }
2301
2371
  async sendCredential(did, options = {}) {
@@ -2325,13 +2395,12 @@ class Keymaster {
2325
2395
  throw new InvalidParameterError("did is not a credential");
2326
2396
  }
2327
2397
  if (!credential ||
2328
- !credential.credential ||
2329
2398
  !credential.credentialSubject ||
2330
2399
  !credential.credentialSubject.id) {
2331
2400
  throw new InvalidParameterError('credential');
2332
2401
  }
2333
- delete credential.signature;
2334
- const signed = await this.addSignature(credential);
2402
+ delete credential.proof;
2403
+ const signed = await this.addProof(credential);
2335
2404
  const msg = JSON.stringify(signed);
2336
2405
  const id = await this.fetchIdInfo();
2337
2406
  const senderKeypair = await this.fetchKeyPair();
@@ -2425,8 +2494,8 @@ class Keymaster {
2425
2494
  data.manifest = {};
2426
2495
  }
2427
2496
  if (!reveal) {
2428
- // Remove the credential values
2429
- vc.credential = null;
2497
+ // Remove the claim values, keep only the subject id
2498
+ vc.credentialSubject = { id: vc.credentialSubject.id };
2430
2499
  }
2431
2500
  data.manifest[credential] = vc;
2432
2501
  const ok = await this.updateDID(id.did, { didDocumentData: doc.didDocumentData });
@@ -2484,8 +2553,8 @@ class Keymaster {
2484
2553
  // Attestor not trusted by Verifier
2485
2554
  continue;
2486
2555
  }
2487
- if (doc.type && !doc.type.includes(credential.schema)) {
2488
- // Wrong type
2556
+ if (doc.credentialSchema?.id !== credential.schema) {
2557
+ // Wrong schema
2489
2558
  continue;
2490
2559
  }
2491
2560
  // TBD test for VC expiry too
@@ -2610,7 +2679,7 @@ class Keymaster {
2610
2679
  continue;
2611
2680
  }
2612
2681
  const vp = await this.decryptJSON(credential.vp);
2613
- const isValid = await this.verifySignature(vp);
2682
+ const isValid = await this.verifyProof(vp);
2614
2683
  if (!isValid) {
2615
2684
  continue;
2616
2685
  }
@@ -2618,8 +2687,8 @@ class Keymaster {
2618
2687
  continue;
2619
2688
  }
2620
2689
  // Check VP against VCs specified in challenge
2621
- if (vp.type.length >= 2 && vp.type[1].startsWith('did:')) {
2622
- const schema = vp.type[1];
2690
+ if (vp.credentialSchema?.id) {
2691
+ const schema = vp.credentialSchema.id;
2623
2692
  const credential = challenge.credentials?.find(item => item.schema === schema);
2624
2693
  if (!credential) {
2625
2694
  continue;
@@ -3117,7 +3186,7 @@ class Keymaster {
3117
3186
  delete poll.results;
3118
3187
  return this.updateAsset(pollId, { poll });
3119
3188
  }
3120
- async createGroupVault(options = {}) {
3189
+ async createVault(options = {}) {
3121
3190
  const id = await this.fetchIdInfo();
3122
3191
  const idKeypair = await this.fetchKeyPair();
3123
3192
  // version defaults to 1. To make version undefined (unit testing), set options.version to 0
@@ -3132,7 +3201,7 @@ class Keymaster {
3132
3201
  const members = this.cipher.encryptMessage(publicJwk, vaultKeypair.privateJwk, JSON.stringify({}));
3133
3202
  const items = this.cipher.encryptMessage(vaultKeypair.publicJwk, vaultKeypair.privateJwk, JSON.stringify({}));
3134
3203
  const sha256 = this.cipher.hashJSON({});
3135
- const groupVault = {
3204
+ const vault = {
3136
3205
  version,
3137
3206
  publicJwk: vaultKeypair.publicJwk,
3138
3207
  salt,
@@ -3142,46 +3211,46 @@ class Keymaster {
3142
3211
  items,
3143
3212
  sha256,
3144
3213
  };
3145
- await this.addMemberKey(groupVault, id.did, vaultKeypair.privateJwk);
3146
- return this.createAsset({ groupVault }, options);
3214
+ await this.addMemberKey(vault, id.did, vaultKeypair.privateJwk);
3215
+ return this.createAsset({ vault }, options);
3147
3216
  }
3148
- async getGroupVault(groupVaultId, options) {
3149
- const asset = await this.resolveAsset(groupVaultId, options);
3150
- if (!asset.groupVault) {
3151
- throw new InvalidParameterError('groupVaultId');
3217
+ async getVault(vaultId, options) {
3218
+ const asset = await this.resolveAsset(vaultId, options);
3219
+ if (!asset.vault) {
3220
+ throw new InvalidParameterError('vaultId');
3152
3221
  }
3153
- return asset.groupVault;
3222
+ return asset.vault;
3154
3223
  }
3155
- async testGroupVault(id, options) {
3224
+ async testVault(id, options) {
3156
3225
  try {
3157
- const groupVault = await this.getGroupVault(id, options);
3158
- return groupVault !== null;
3226
+ const vault = await this.getVault(id, options);
3227
+ return vault !== null;
3159
3228
  }
3160
3229
  catch (error) {
3161
3230
  return false;
3162
3231
  }
3163
3232
  }
3164
- generateSaltedId(groupVault, memberDID) {
3165
- if (!groupVault.version) {
3166
- return this.cipher.hashMessage(groupVault.salt + memberDID);
3233
+ generateSaltedId(vault, memberDID) {
3234
+ if (!vault.version) {
3235
+ return this.cipher.hashMessage(vault.salt + memberDID);
3167
3236
  }
3168
3237
  const suffix = memberDID.split(':').pop();
3169
- return this.cipher.hashMessage(groupVault.salt + suffix);
3238
+ return this.cipher.hashMessage(vault.salt + suffix);
3170
3239
  }
3171
- async decryptGroupVault(groupVault) {
3240
+ async decryptVault(vault) {
3172
3241
  const wallet = await this.loadWallet();
3173
3242
  const id = await this.fetchIdInfo();
3174
- const myMemberId = this.generateSaltedId(groupVault, id.did);
3175
- const myVaultKey = groupVault.keys[myMemberId];
3243
+ const myMemberId = this.generateSaltedId(vault, id.did);
3244
+ const myVaultKey = vault.keys[myMemberId];
3176
3245
  if (!myVaultKey) {
3177
- throw new KeymasterError('No access to group vault');
3246
+ throw new KeymasterError('No access to vault');
3178
3247
  }
3179
- const privKeyJSON = await this.decryptWithDerivedKeys(wallet, id, groupVault.publicJwk, myVaultKey);
3248
+ const privKeyJSON = await this.decryptWithDerivedKeys(wallet, id, vault.publicJwk, myVaultKey);
3180
3249
  const privateJwk = JSON.parse(privKeyJSON);
3181
3250
  let config = {};
3182
3251
  let isOwner = false;
3183
3252
  try {
3184
- const configJSON = await this.decryptWithDerivedKeys(wallet, id, groupVault.publicJwk, groupVault.config);
3253
+ const configJSON = await this.decryptWithDerivedKeys(wallet, id, vault.publicJwk, vault.config);
3185
3254
  config = JSON.parse(configJSON);
3186
3255
  isOwner = true;
3187
3256
  }
@@ -3191,7 +3260,7 @@ class Keymaster {
3191
3260
  let members = {};
3192
3261
  if (config.secretMembers) {
3193
3262
  try {
3194
- const membersJSON = await this.decryptWithDerivedKeys(wallet, id, groupVault.publicJwk, groupVault.members);
3263
+ const membersJSON = await this.decryptWithDerivedKeys(wallet, id, vault.publicJwk, vault.members);
3195
3264
  members = JSON.parse(membersJSON);
3196
3265
  }
3197
3266
  catch (error) {
@@ -3199,13 +3268,13 @@ class Keymaster {
3199
3268
  }
3200
3269
  else {
3201
3270
  try {
3202
- const membersJSON = this.cipher.decryptMessage(groupVault.publicJwk, privateJwk, groupVault.members);
3271
+ const membersJSON = this.cipher.decryptMessage(vault.publicJwk, privateJwk, vault.members);
3203
3272
  members = JSON.parse(membersJSON);
3204
3273
  }
3205
3274
  catch (error) {
3206
3275
  }
3207
3276
  }
3208
- const itemsJSON = this.cipher.decryptMessage(groupVault.publicJwk, privateJwk, groupVault.items);
3277
+ const itemsJSON = this.cipher.decryptMessage(vault.publicJwk, privateJwk, vault.items);
3209
3278
  const items = JSON.parse(itemsJSON);
3210
3279
  return {
3211
3280
  isOwner,
@@ -3215,7 +3284,7 @@ class Keymaster {
3215
3284
  items,
3216
3285
  };
3217
3286
  }
3218
- async checkGroupVaultOwner(vaultId) {
3287
+ async checkVaultOwner(vaultId) {
3219
3288
  const id = await this.fetchIdInfo();
3220
3289
  const vaultDoc = await this.resolveDID(vaultId);
3221
3290
  const controller = vaultDoc.didDocument?.controller;
@@ -3224,30 +3293,30 @@ class Keymaster {
3224
3293
  }
3225
3294
  return controller;
3226
3295
  }
3227
- async addMemberKey(groupVault, memberDID, privateJwk) {
3296
+ async addMemberKey(vault, memberDID, privateJwk) {
3228
3297
  const memberDoc = await this.resolveDID(memberDID, { confirm: true });
3229
3298
  const memberPublicJwk = this.getPublicKeyJwk(memberDoc);
3230
3299
  const memberKey = this.cipher.encryptMessage(memberPublicJwk, privateJwk, JSON.stringify(privateJwk));
3231
- const memberKeyId = this.generateSaltedId(groupVault, memberDID);
3232
- groupVault.keys[memberKeyId] = memberKey;
3300
+ const memberKeyId = this.generateSaltedId(vault, memberDID);
3301
+ vault.keys[memberKeyId] = memberKey;
3233
3302
  }
3234
- async checkVaultVersion(vaultId, groupVault) {
3235
- if (groupVault.version === 1) {
3303
+ async checkVaultVersion(vaultId, vault) {
3304
+ if (vault.version === 1) {
3236
3305
  return;
3237
3306
  }
3238
- if (!groupVault.version) {
3307
+ if (!vault.version) {
3239
3308
  const id = await this.fetchIdInfo();
3240
- const { privateJwk, members } = await this.decryptGroupVault(groupVault);
3241
- groupVault.version = 1;
3242
- groupVault.keys = {};
3243
- await this.addMemberKey(groupVault, id.did, privateJwk);
3309
+ const { privateJwk, members } = await this.decryptVault(vault);
3310
+ vault.version = 1;
3311
+ vault.keys = {};
3312
+ await this.addMemberKey(vault, id.did, privateJwk);
3244
3313
  for (const memberDID of Object.keys(members)) {
3245
- await this.addMemberKey(groupVault, memberDID, privateJwk);
3314
+ await this.addMemberKey(vault, memberDID, privateJwk);
3246
3315
  }
3247
- await this.updateAsset(vaultId, { groupVault });
3316
+ await this.updateAsset(vaultId, { vault });
3248
3317
  return;
3249
3318
  }
3250
- throw new KeymasterError('Unsupported group vault version');
3319
+ throw new KeymasterError('Unsupported vault version');
3251
3320
  }
3252
3321
  getAgentDID(doc) {
3253
3322
  if (doc.didDocumentRegistration?.type !== 'agent') {
@@ -3259,11 +3328,11 @@ class Keymaster {
3259
3328
  }
3260
3329
  return did;
3261
3330
  }
3262
- async addGroupVaultMember(vaultId, memberId) {
3263
- const owner = await this.checkGroupVaultOwner(vaultId);
3331
+ async addVaultMember(vaultId, memberId) {
3332
+ const owner = await this.checkVaultOwner(vaultId);
3264
3333
  const idKeypair = await this.fetchKeyPair();
3265
- const groupVault = await this.getGroupVault(vaultId);
3266
- const { privateJwk, config, members } = await this.decryptGroupVault(groupVault);
3334
+ const vault = await this.getVault(vaultId);
3335
+ const { privateJwk, config, members } = await this.decryptVault(vault);
3267
3336
  const memberDoc = await this.resolveDID(memberId, { confirm: true });
3268
3337
  const memberDID = this.getAgentDID(memberDoc);
3269
3338
  // Don't allow adding the vault owner
@@ -3271,16 +3340,16 @@ class Keymaster {
3271
3340
  return false;
3272
3341
  }
3273
3342
  members[memberDID] = { added: new Date().toISOString() };
3274
- const publicJwk = config.secretMembers ? idKeypair.publicJwk : groupVault.publicJwk;
3275
- groupVault.members = this.cipher.encryptMessage(publicJwk, privateJwk, JSON.stringify(members));
3276
- await this.addMemberKey(groupVault, memberDID, privateJwk);
3277
- return this.updateAsset(vaultId, { groupVault });
3343
+ const publicJwk = config.secretMembers ? idKeypair.publicJwk : vault.publicJwk;
3344
+ vault.members = this.cipher.encryptMessage(publicJwk, privateJwk, JSON.stringify(members));
3345
+ await this.addMemberKey(vault, memberDID, privateJwk);
3346
+ return this.updateAsset(vaultId, { vault });
3278
3347
  }
3279
- async removeGroupVaultMember(vaultId, memberId) {
3280
- const owner = await this.checkGroupVaultOwner(vaultId);
3348
+ async removeVaultMember(vaultId, memberId) {
3349
+ const owner = await this.checkVaultOwner(vaultId);
3281
3350
  const idKeypair = await this.fetchKeyPair();
3282
- const groupVault = await this.getGroupVault(vaultId);
3283
- const { privateJwk, config, members } = await this.decryptGroupVault(groupVault);
3351
+ const vault = await this.getVault(vaultId);
3352
+ const { privateJwk, config, members } = await this.decryptVault(vault);
3284
3353
  const memberDoc = await this.resolveDID(memberId, { confirm: true });
3285
3354
  const memberDID = this.getAgentDID(memberDoc);
3286
3355
  // Don't allow removing the vault owner
@@ -3288,26 +3357,26 @@ class Keymaster {
3288
3357
  return false;
3289
3358
  }
3290
3359
  delete members[memberDID];
3291
- const publicJwk = config.secretMembers ? idKeypair.publicJwk : groupVault.publicJwk;
3292
- groupVault.members = this.cipher.encryptMessage(publicJwk, privateJwk, JSON.stringify(members));
3293
- const memberKeyId = this.generateSaltedId(groupVault, memberDID);
3294
- delete groupVault.keys[memberKeyId];
3295
- return this.updateAsset(vaultId, { groupVault });
3296
- }
3297
- async listGroupVaultMembers(vaultId) {
3298
- const groupVault = await this.getGroupVault(vaultId);
3299
- const { members, isOwner } = await this.decryptGroupVault(groupVault);
3360
+ const publicJwk = config.secretMembers ? idKeypair.publicJwk : vault.publicJwk;
3361
+ vault.members = this.cipher.encryptMessage(publicJwk, privateJwk, JSON.stringify(members));
3362
+ const memberKeyId = this.generateSaltedId(vault, memberDID);
3363
+ delete vault.keys[memberKeyId];
3364
+ return this.updateAsset(vaultId, { vault });
3365
+ }
3366
+ async listVaultMembers(vaultId) {
3367
+ const vault = await this.getVault(vaultId);
3368
+ const { members, isOwner } = await this.decryptVault(vault);
3300
3369
  if (isOwner) {
3301
- await this.checkVaultVersion(vaultId, groupVault);
3370
+ await this.checkVaultVersion(vaultId, vault);
3302
3371
  }
3303
3372
  return members;
3304
3373
  }
3305
- async addGroupVaultItem(vaultId, name, buffer) {
3306
- await this.checkGroupVaultOwner(vaultId);
3307
- const groupVault = await this.getGroupVault(vaultId);
3308
- const { privateJwk, items } = await this.decryptGroupVault(groupVault);
3374
+ async addVaultItem(vaultId, name, buffer) {
3375
+ await this.checkVaultOwner(vaultId);
3376
+ const vault = await this.getVault(vaultId);
3377
+ const { privateJwk, items } = await this.decryptVault(vault);
3309
3378
  const validName = this.validateName(name);
3310
- const encryptedData = this.cipher.encryptBytes(groupVault.publicJwk, privateJwk, buffer);
3379
+ const encryptedData = this.cipher.encryptBytes(vault.publicJwk, privateJwk, buffer);
3311
3380
  const cid = await this.gatekeeper.addText(encryptedData);
3312
3381
  const sha256 = this.cipher.hashMessage(buffer);
3313
3382
  const type = await this.getMimeType(buffer);
@@ -3320,32 +3389,32 @@ class Keymaster {
3320
3389
  added: new Date().toISOString(),
3321
3390
  data,
3322
3391
  };
3323
- groupVault.items = this.cipher.encryptMessage(groupVault.publicJwk, privateJwk, JSON.stringify(items));
3324
- groupVault.sha256 = this.cipher.hashJSON(items);
3325
- return this.updateAsset(vaultId, { groupVault });
3326
- }
3327
- async removeGroupVaultItem(vaultId, name) {
3328
- await this.checkGroupVaultOwner(vaultId);
3329
- const groupVault = await this.getGroupVault(vaultId);
3330
- const { privateJwk, items } = await this.decryptGroupVault(groupVault);
3392
+ vault.items = this.cipher.encryptMessage(vault.publicJwk, privateJwk, JSON.stringify(items));
3393
+ vault.sha256 = this.cipher.hashJSON(items);
3394
+ return this.updateAsset(vaultId, { vault });
3395
+ }
3396
+ async removeVaultItem(vaultId, name) {
3397
+ await this.checkVaultOwner(vaultId);
3398
+ const vault = await this.getVault(vaultId);
3399
+ const { privateJwk, items } = await this.decryptVault(vault);
3331
3400
  delete items[name];
3332
- groupVault.items = this.cipher.encryptMessage(groupVault.publicJwk, privateJwk, JSON.stringify(items));
3333
- groupVault.sha256 = this.cipher.hashJSON(items);
3334
- return this.updateAsset(vaultId, { groupVault });
3401
+ vault.items = this.cipher.encryptMessage(vault.publicJwk, privateJwk, JSON.stringify(items));
3402
+ vault.sha256 = this.cipher.hashJSON(items);
3403
+ return this.updateAsset(vaultId, { vault });
3335
3404
  }
3336
- async listGroupVaultItems(vaultId, options) {
3337
- const groupVault = await this.getGroupVault(vaultId, options);
3338
- const { items } = await this.decryptGroupVault(groupVault);
3405
+ async listVaultItems(vaultId, options) {
3406
+ const vault = await this.getVault(vaultId, options);
3407
+ const { items } = await this.decryptVault(vault);
3339
3408
  return items;
3340
3409
  }
3341
- async getGroupVaultItem(vaultId, name, options) {
3410
+ async getVaultItem(vaultId, name, options) {
3342
3411
  try {
3343
- const groupVault = await this.getGroupVault(vaultId, options);
3344
- const { privateJwk, items } = await this.decryptGroupVault(groupVault);
3412
+ const vault = await this.getVault(vaultId, options);
3413
+ const { privateJwk, items } = await this.decryptVault(vault);
3345
3414
  if (items[name]) {
3346
3415
  const encryptedData = items[name].data || await this.gatekeeper.getText(items[name].cid);
3347
3416
  if (encryptedData) {
3348
- const bytes = this.cipher.decryptBytes(groupVault.publicJwk, privateJwk, encryptedData);
3417
+ const bytes = this.cipher.decryptBytes(vault.publicJwk, privateJwk, encryptedData);
3349
3418
  return Buffer.from(bytes);
3350
3419
  }
3351
3420
  }
@@ -3474,28 +3543,28 @@ class Keymaster {
3474
3543
  }
3475
3544
  async createDmail(message, options = {}) {
3476
3545
  const dmail = await this.verifyDmail(message);
3477
- const did = await this.createGroupVault(options);
3546
+ const did = await this.createVault(options);
3478
3547
  for (const toDID of dmail.to) {
3479
- await this.addGroupVaultMember(did, toDID);
3548
+ await this.addVaultMember(did, toDID);
3480
3549
  }
3481
3550
  for (const ccDID of dmail.cc) {
3482
- await this.addGroupVaultMember(did, ccDID);
3551
+ await this.addVaultMember(did, ccDID);
3483
3552
  }
3484
3553
  const buffer = Buffer.from(JSON.stringify({ dmail }), 'utf-8');
3485
- await this.addGroupVaultItem(did, exports.DmailTags.DMAIL, buffer);
3554
+ await this.addVaultItem(did, exports.DmailTags.DMAIL, buffer);
3486
3555
  await this.fileDmail(did, [exports.DmailTags.DRAFT]);
3487
3556
  return did;
3488
3557
  }
3489
3558
  async updateDmail(did, message) {
3490
3559
  const dmail = await this.verifyDmail(message);
3491
3560
  for (const toDID of dmail.to) {
3492
- await this.addGroupVaultMember(did, toDID);
3561
+ await this.addVaultMember(did, toDID);
3493
3562
  }
3494
3563
  for (const ccDID of dmail.cc) {
3495
- await this.addGroupVaultMember(did, ccDID);
3564
+ await this.addVaultMember(did, ccDID);
3496
3565
  }
3497
3566
  const buffer = Buffer.from(JSON.stringify({ dmail }), 'utf-8');
3498
- return this.addGroupVaultItem(did, exports.DmailTags.DMAIL, buffer);
3567
+ return this.addVaultItem(did, exports.DmailTags.DMAIL, buffer);
3499
3568
  }
3500
3569
  async sendDmail(did) {
3501
3570
  const dmail = await this.getDmailMessage(did);
@@ -3515,11 +3584,11 @@ class Keymaster {
3515
3584
  return notice;
3516
3585
  }
3517
3586
  async getDmailMessage(did, options) {
3518
- const isGroupVault = await this.testGroupVault(did, options);
3519
- if (!isGroupVault) {
3587
+ const isVault = await this.testVault(did, options);
3588
+ if (!isVault) {
3520
3589
  return null;
3521
3590
  }
3522
- const buffer = await this.getGroupVaultItem(did, exports.DmailTags.DMAIL, options);
3591
+ const buffer = await this.getVaultItem(did, exports.DmailTags.DMAIL, options);
3523
3592
  if (!buffer) {
3524
3593
  return null;
3525
3594
  }
@@ -3532,7 +3601,7 @@ class Keymaster {
3532
3601
  }
3533
3602
  }
3534
3603
  async listDmailAttachments(did, options) {
3535
- let items = await this.listGroupVaultItems(did, options);
3604
+ let items = await this.listVaultItems(did, options);
3536
3605
  delete items[exports.DmailTags.DMAIL]; // Remove the dmail item itself from attachments
3537
3606
  return items;
3538
3607
  }
@@ -3540,16 +3609,16 @@ class Keymaster {
3540
3609
  if (name === exports.DmailTags.DMAIL) {
3541
3610
  throw new InvalidParameterError('Cannot add attachment with reserved name "dmail"');
3542
3611
  }
3543
- return this.addGroupVaultItem(did, name, buffer);
3612
+ return this.addVaultItem(did, name, buffer);
3544
3613
  }
3545
3614
  async removeDmailAttachment(did, name) {
3546
3615
  if (name === exports.DmailTags.DMAIL) {
3547
3616
  throw new InvalidParameterError('Cannot remove attachment with reserved name "dmail"');
3548
3617
  }
3549
- return this.removeGroupVaultItem(did, name);
3618
+ return this.removeVaultItem(did, name);
3550
3619
  }
3551
3620
  async getDmailAttachment(did, name) {
3552
- return this.getGroupVaultItem(did, name);
3621
+ return this.getVaultItem(did, name);
3553
3622
  }
3554
3623
  async importDmail(did) {
3555
3624
  const dmail = await this.getDmailMessage(did);