@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.
@@ -1,9 +1,18 @@
1
1
  import { imageSize } from 'image-size';
2
2
  import { fileTypeFromBuffer } from 'file-type';
3
+ import { base64url } from 'multiformats/bases/base64';
3
4
  import { InvalidDIDError, InvalidParameterError, KeymasterError, UnknownIDError } from '@didcid/common/errors';
4
5
  import { isWalletEncFile, isWalletFile } from './db/typeGuards.js';
5
6
  import { isValidDID } from '@didcid/ipfs/utils';
6
7
  import { decMnemonic, encMnemonic } from "./encryption.js";
8
+ function hexToBase64url(hex) {
9
+ const bytes = Buffer.from(hex, 'hex');
10
+ return base64url.baseEncode(bytes);
11
+ }
12
+ function base64urlToHex(b64) {
13
+ const bytes = base64url.baseDecode(b64);
14
+ return Buffer.from(bytes).toString('hex');
15
+ }
7
16
  const DefaultSchema = {
8
17
  "$schema": "http://json-schema.org/draft-07/schema#",
9
18
  "type": "object",
@@ -301,13 +310,15 @@ export default class Keymaster {
301
310
  publicJwk: keypair.publicJwk,
302
311
  };
303
312
  const msgHash = this.cipher.hashJSON(operation);
304
- const signature = this.cipher.signHash(msgHash, keypair.privateJwk);
313
+ const signatureHex = this.cipher.signHash(msgHash, keypair.privateJwk);
305
314
  const signed = {
306
315
  ...operation,
307
- signature: {
308
- signed: new Date(0).toISOString(),
309
- hash: msgHash,
310
- value: signature
316
+ proof: {
317
+ type: "EcdsaSecp256k1Signature2019",
318
+ created: new Date(0).toISOString(),
319
+ verificationMethod: "#key-1",
320
+ proofPurpose: "authentication",
321
+ proofValue: hexToBase64url(signatureHex),
311
322
  }
312
323
  };
313
324
  const did = await this.gatekeeper.createDID(signed);
@@ -328,14 +339,15 @@ export default class Keymaster {
328
339
  doc,
329
340
  };
330
341
  const msgHash = this.cipher.hashJSON(operation);
331
- const signature = this.cipher.signHash(msgHash, keypair.privateJwk);
342
+ const signatureHex = this.cipher.signHash(msgHash, keypair.privateJwk);
332
343
  const signed = {
333
344
  ...operation,
334
- signature: {
335
- signer: did,
336
- signed: new Date().toISOString(),
337
- hash: msgHash,
338
- value: signature,
345
+ proof: {
346
+ type: "EcdsaSecp256k1Signature2019",
347
+ created: new Date().toISOString(),
348
+ verificationMethod: `${did}#key-1`,
349
+ proofPurpose: "authentication",
350
+ proofValue: hexToBase64url(signatureHex),
339
351
  }
340
352
  };
341
353
  return await this.gatekeeper.updateDID(signed);
@@ -360,14 +372,15 @@ export default class Keymaster {
360
372
  data: { backup: backup },
361
373
  };
362
374
  const msgHash = this.cipher.hashJSON(operation);
363
- const signature = this.cipher.signHash(msgHash, keypair.privateJwk);
375
+ const signatureHex = this.cipher.signHash(msgHash, keypair.privateJwk);
364
376
  const signed = {
365
377
  ...operation,
366
- signature: {
367
- signer: seedBank.didDocument?.id,
368
- signed: new Date().toISOString(),
369
- hash: msgHash,
370
- value: signature,
378
+ proof: {
379
+ type: "EcdsaSecp256k1Signature2019",
380
+ created: new Date().toISOString(),
381
+ verificationMethod: `${seedBank.didDocument?.id}#key-1`,
382
+ proofPurpose: "authentication",
383
+ proofValue: hexToBase64url(signatureHex),
371
384
  }
372
385
  };
373
386
  const backupDID = await this.gatekeeper.createDID(signed);
@@ -548,7 +561,7 @@ export default class Keymaster {
548
561
  controller: id.did,
549
562
  data,
550
563
  };
551
- const signed = await this.addSignature(operation, controller);
564
+ const signed = await this.addProof(operation, controller, "authentication");
552
565
  const did = await this.gatekeeper.createDID(signed);
553
566
  // Keep assets that will be garbage-collected out of the owned list
554
567
  if (!validUntil) {
@@ -737,7 +750,7 @@ export default class Keymaster {
737
750
  throw new InvalidParameterError('did not encrypted JSON');
738
751
  }
739
752
  }
740
- async addSignature(obj, controller) {
753
+ async addProof(obj, controller, proofPurpose = "assertionMethod") {
741
754
  if (obj == null) {
742
755
  throw new InvalidParameterError('obj');
743
756
  }
@@ -745,18 +758,23 @@ export default class Keymaster {
745
758
  const id = await this.fetchIdInfo(controller);
746
759
  const keypair = await this.fetchKeyPair(controller);
747
760
  if (!keypair) {
748
- throw new KeymasterError('addSignature: no keypair');
761
+ throw new KeymasterError('addProof: no keypair');
749
762
  }
763
+ // Get the key fragment from the DID document
764
+ const doc = await this.resolveDID(id.did, { confirm: true });
765
+ const keyFragment = doc.didDocument?.verificationMethod?.[0]?.id || '#key-1';
750
766
  try {
751
767
  const msgHash = this.cipher.hashJSON(obj);
752
- const signature = this.cipher.signHash(msgHash, keypair.privateJwk);
768
+ const signatureHex = this.cipher.signHash(msgHash, keypair.privateJwk);
769
+ const proofValue = hexToBase64url(signatureHex);
753
770
  return {
754
771
  ...obj,
755
- signature: {
756
- signer: id.did,
757
- signed: new Date().toISOString(),
758
- hash: msgHash,
759
- value: signature,
772
+ proof: {
773
+ type: "EcdsaSecp256k1Signature2019",
774
+ created: new Date().toISOString(),
775
+ verificationMethod: `${id.did}${keyFragment}`,
776
+ proofPurpose,
777
+ proofValue,
760
778
  }
761
779
  };
762
780
  }
@@ -764,24 +782,27 @@ export default class Keymaster {
764
782
  throw new InvalidParameterError('obj');
765
783
  }
766
784
  }
767
- async verifySignature(obj) {
768
- if (!obj?.signature) {
785
+ async verifyProof(obj) {
786
+ if (!obj?.proof) {
769
787
  return false;
770
788
  }
771
- const { signature } = obj;
772
- if (!signature.signer) {
789
+ const { proof } = obj;
790
+ if (proof.type !== "EcdsaSecp256k1Signature2019") {
773
791
  return false;
774
792
  }
775
- const jsonCopy = JSON.parse(JSON.stringify(obj));
776
- delete jsonCopy.signature;
777
- const msgHash = this.cipher.hashJSON(jsonCopy);
778
- if (signature.hash && signature.hash !== msgHash) {
793
+ if (!proof.verificationMethod) {
779
794
  return false;
780
795
  }
781
- const doc = await this.resolveDID(signature.signer, { versionTime: signature.signed });
796
+ // Extract DID from verificationMethod
797
+ const [signerDid] = proof.verificationMethod.split('#');
798
+ const jsonCopy = JSON.parse(JSON.stringify(obj));
799
+ delete jsonCopy.proof;
800
+ const msgHash = this.cipher.hashJSON(jsonCopy);
801
+ const doc = await this.resolveDID(signerDid, { versionTime: proof.created });
782
802
  const publicJwk = this.getPublicKeyJwk(doc);
783
803
  try {
784
- return this.cipher.verifySig(msgHash, signature.value, publicJwk);
804
+ const signatureHex = base64urlToHex(proof.proofValue);
805
+ return this.cipher.verifySig(msgHash, signatureHex, publicJwk);
785
806
  }
786
807
  catch (error) {
787
808
  return false;
@@ -810,7 +831,7 @@ export default class Keymaster {
810
831
  else if (current.didDocumentRegistration?.type === 'asset') {
811
832
  controller = current.didDocument?.controller;
812
833
  }
813
- const signed = await this.addSignature(operation, controller);
834
+ const signed = await this.addProof(operation, controller, "authentication");
814
835
  return this.gatekeeper.updateDID(signed);
815
836
  }
816
837
  async revokeDID(id) {
@@ -832,7 +853,7 @@ export default class Keymaster {
832
853
  else if (current.didDocumentRegistration?.type === 'asset') {
833
854
  controller = current.didDocument?.controller;
834
855
  }
835
- const signed = await this.addSignature(operation, controller);
856
+ const signed = await this.addProof(operation, controller, "authentication");
836
857
  const ok = await this.gatekeeper.deleteDID(signed);
837
858
  if (ok && current.didDocument?.controller) {
838
859
  await this.removeFromOwned(did, current.didDocument.controller);
@@ -912,9 +933,13 @@ export default class Keymaster {
912
933
  }
913
934
  const controller = docs.didDocument?.controller || docs.didDocument?.id;
914
935
  const isOwned = await this.idInWallet(controller);
915
- // Augment the DID document metadata with the DID ownership status
936
+ // Convert versionSequence string to numeric version
937
+ const versionSequence = docs.didDocumentMetadata?.versionSequence;
938
+ const version = versionSequence ? parseInt(versionSequence, 10) : undefined;
939
+ // Augment the DID document metadata with the DID ownership status and numeric version
916
940
  docs.didDocumentMetadata = {
917
941
  ...docs.didDocumentMetadata,
942
+ version,
918
943
  isOwned,
919
944
  };
920
945
  return docs;
@@ -1033,13 +1058,15 @@ export default class Keymaster {
1033
1058
  publicJwk: keypair.publicJwk,
1034
1059
  };
1035
1060
  const msgHash = this.cipher.hashJSON(operation);
1036
- const signature = this.cipher.signHash(msgHash, keypair.privateJwk);
1061
+ const signatureHex = this.cipher.signHash(msgHash, keypair.privateJwk);
1037
1062
  const signed = {
1038
1063
  ...operation,
1039
- signature: {
1040
- signed: new Date().toISOString(),
1041
- hash: msgHash,
1042
- value: signature
1064
+ proof: {
1065
+ type: "EcdsaSecp256k1Signature2019",
1066
+ created: new Date().toISOString(),
1067
+ verificationMethod: "#key-1",
1068
+ proofPurpose: "authentication",
1069
+ proofValue: hexToBase64url(signatureHex),
1043
1070
  },
1044
1071
  };
1045
1072
  return signed;
@@ -1093,10 +1120,10 @@ export default class Keymaster {
1093
1120
  if (!registry) {
1094
1121
  throw new InvalidParameterError('no registry found for agent DID');
1095
1122
  }
1096
- const vaultDid = await this.createAsset({ backup: backup }, { registry, controller: name });
1123
+ const backupStoreDid = await this.createAsset({ backup: backup }, { registry, controller: name });
1097
1124
  if (doc.didDocumentData) {
1098
1125
  const currentData = doc.didDocumentData;
1099
- const updatedData = { ...currentData, vault: vaultDid };
1126
+ const updatedData = { ...currentData, backupStore: backupStoreDid };
1100
1127
  return this.updateDID(name, { didDocumentData: updatedData });
1101
1128
  }
1102
1129
  return false;
@@ -1106,14 +1133,14 @@ export default class Keymaster {
1106
1133
  const keypair = await this.hdKeyPair();
1107
1134
  const doc = await this.resolveDID(did);
1108
1135
  const docData = doc.didDocumentData;
1109
- if (!docData.vault) {
1110
- throw new InvalidDIDError('didDocumentData missing vault');
1136
+ if (!docData.backupStore) {
1137
+ throw new InvalidDIDError('didDocumentData missing backupStore');
1111
1138
  }
1112
- const vault = await this.resolveAsset(docData.vault);
1113
- if (typeof vault.backup !== 'string') {
1114
- throw new InvalidDIDError('backup not found in vault');
1139
+ const backupStore = await this.resolveAsset(docData.backupStore);
1140
+ if (typeof backupStore.backup !== 'string') {
1141
+ throw new InvalidDIDError('backup not found in backupStore');
1115
1142
  }
1116
- const backup = this.cipher.decryptMessage(keypair.publicJwk, keypair.privateJwk, vault.backup);
1143
+ const backup = this.cipher.decryptMessage(keypair.publicJwk, keypair.privateJwk, backupStore.backup);
1117
1144
  const data = JSON.parse(backup);
1118
1145
  await this.mutateWallet((wallet) => {
1119
1146
  if (wallet.ids[data.name]) {
@@ -1157,6 +1184,7 @@ export default class Keymaster {
1157
1184
  ...doc.didDocument,
1158
1185
  verificationMethod: [vmethod],
1159
1186
  authentication: [vmethod.id],
1187
+ assertionMethod: [vmethod.id],
1160
1188
  };
1161
1189
  ok = await this.updateDID(id.did, { didDocument: updatedDidDocument });
1162
1190
  if (!ok) {
@@ -1169,7 +1197,7 @@ export default class Keymaster {
1169
1197
  async listNames(options = {}) {
1170
1198
  const { includeIDs = false } = options;
1171
1199
  const wallet = await this.loadWallet();
1172
- const names = wallet.names || {};
1200
+ const names = { ...(wallet.names || {}) };
1173
1201
  if (includeIDs) {
1174
1202
  for (const [name, id] of Object.entries(wallet.ids || {})) {
1175
1203
  names[name] = id.did;
@@ -1207,42 +1235,60 @@ export default class Keymaster {
1207
1235
  const doc = await this.resolveDID(id);
1208
1236
  return doc.didDocumentRegistration?.type === 'agent';
1209
1237
  }
1210
- async bindCredential(schemaId, subjectId, options = {}) {
1211
- let { validFrom, validUntil, credential } = options;
1238
+ async bindCredential(subjectId, options = {}) {
1239
+ let { schema, validFrom, validUntil, claims, types } = options;
1212
1240
  if (!validFrom) {
1213
1241
  validFrom = new Date().toISOString();
1214
1242
  }
1215
1243
  const id = await this.fetchIdInfo();
1216
- const type = await this.lookupDID(schemaId);
1217
1244
  const subjectDID = await this.lookupDID(subjectId);
1218
- if (!credential) {
1219
- const schema = await this.getSchema(type);
1220
- credential = this.generateSchema(schema);
1221
- }
1222
- return {
1245
+ const vc = {
1223
1246
  "@context": [
1224
1247
  "https://www.w3.org/ns/credentials/v2",
1225
1248
  "https://www.w3.org/ns/credentials/examples/v2"
1226
1249
  ],
1227
- type: ["VerifiableCredential", type],
1250
+ type: ["VerifiableCredential", ...(types || [])],
1228
1251
  issuer: id.did,
1229
1252
  validFrom,
1230
1253
  validUntil,
1231
1254
  credentialSubject: {
1232
1255
  id: subjectDID,
1233
1256
  },
1234
- credential,
1235
1257
  };
1258
+ // If schema provided, add credentialSchema and generate claims from schema
1259
+ if (schema) {
1260
+ const schemaDID = await this.lookupDID(schema);
1261
+ const schemaDoc = await this.getSchema(schemaDID);
1262
+ if (!claims && schemaDoc) {
1263
+ claims = this.generateSchema(schemaDoc);
1264
+ }
1265
+ // If schema has $credentialTypes, add them to credential types (avoiding duplicates)
1266
+ if (schemaDoc?.$credentialTypes) {
1267
+ const newTypes = schemaDoc.$credentialTypes.filter(t => !vc.type.includes(t));
1268
+ vc.type.push(...newTypes);
1269
+ }
1270
+ vc.credentialSchema = {
1271
+ id: schemaDID,
1272
+ type: "JsonSchema",
1273
+ };
1274
+ }
1275
+ if (claims) {
1276
+ vc.credentialSubject = {
1277
+ id: subjectDID,
1278
+ ...claims,
1279
+ };
1280
+ }
1281
+ return vc;
1236
1282
  }
1237
1283
  async issueCredential(credential, options = {}) {
1238
1284
  const id = await this.fetchIdInfo();
1239
1285
  if (options.schema && options.subject) {
1240
- credential = await this.bindCredential(options.schema, options.subject, { credential, ...options });
1286
+ credential = await this.bindCredential(options.subject, { schema: options.schema, claims: options.claims, ...options });
1241
1287
  }
1242
1288
  if (credential.issuer !== id.did) {
1243
1289
  throw new InvalidParameterError('credential.issuer');
1244
1290
  }
1245
- const signed = await this.addSignature(credential);
1291
+ const signed = await this.addProof(credential);
1246
1292
  return this.encryptJSON(signed, credential.credentialSubject.id, { ...options, includeHash: true });
1247
1293
  }
1248
1294
  async sendCredential(did, options = {}) {
@@ -1272,13 +1318,12 @@ export default class Keymaster {
1272
1318
  throw new InvalidParameterError("did is not a credential");
1273
1319
  }
1274
1320
  if (!credential ||
1275
- !credential.credential ||
1276
1321
  !credential.credentialSubject ||
1277
1322
  !credential.credentialSubject.id) {
1278
1323
  throw new InvalidParameterError('credential');
1279
1324
  }
1280
- delete credential.signature;
1281
- const signed = await this.addSignature(credential);
1325
+ delete credential.proof;
1326
+ const signed = await this.addProof(credential);
1282
1327
  const msg = JSON.stringify(signed);
1283
1328
  const id = await this.fetchIdInfo();
1284
1329
  const senderKeypair = await this.fetchKeyPair();
@@ -1372,8 +1417,8 @@ export default class Keymaster {
1372
1417
  data.manifest = {};
1373
1418
  }
1374
1419
  if (!reveal) {
1375
- // Remove the credential values
1376
- vc.credential = null;
1420
+ // Remove the claim values, keep only the subject id
1421
+ vc.credentialSubject = { id: vc.credentialSubject.id };
1377
1422
  }
1378
1423
  data.manifest[credential] = vc;
1379
1424
  const ok = await this.updateDID(id.did, { didDocumentData: doc.didDocumentData });
@@ -1431,8 +1476,8 @@ export default class Keymaster {
1431
1476
  // Attestor not trusted by Verifier
1432
1477
  continue;
1433
1478
  }
1434
- if (doc.type && !doc.type.includes(credential.schema)) {
1435
- // Wrong type
1479
+ if (doc.credentialSchema?.id !== credential.schema) {
1480
+ // Wrong schema
1436
1481
  continue;
1437
1482
  }
1438
1483
  // TBD test for VC expiry too
@@ -1557,7 +1602,7 @@ export default class Keymaster {
1557
1602
  continue;
1558
1603
  }
1559
1604
  const vp = await this.decryptJSON(credential.vp);
1560
- const isValid = await this.verifySignature(vp);
1605
+ const isValid = await this.verifyProof(vp);
1561
1606
  if (!isValid) {
1562
1607
  continue;
1563
1608
  }
@@ -1565,8 +1610,8 @@ export default class Keymaster {
1565
1610
  continue;
1566
1611
  }
1567
1612
  // Check VP against VCs specified in challenge
1568
- if (vp.type.length >= 2 && vp.type[1].startsWith('did:')) {
1569
- const schema = vp.type[1];
1613
+ if (vp.credentialSchema?.id) {
1614
+ const schema = vp.credentialSchema.id;
1570
1615
  const credential = challenge.credentials?.find(item => item.schema === schema);
1571
1616
  if (!credential) {
1572
1617
  continue;
@@ -2064,7 +2109,7 @@ export default class Keymaster {
2064
2109
  delete poll.results;
2065
2110
  return this.updateAsset(pollId, { poll });
2066
2111
  }
2067
- async createGroupVault(options = {}) {
2112
+ async createVault(options = {}) {
2068
2113
  const id = await this.fetchIdInfo();
2069
2114
  const idKeypair = await this.fetchKeyPair();
2070
2115
  // version defaults to 1. To make version undefined (unit testing), set options.version to 0
@@ -2079,7 +2124,7 @@ export default class Keymaster {
2079
2124
  const members = this.cipher.encryptMessage(publicJwk, vaultKeypair.privateJwk, JSON.stringify({}));
2080
2125
  const items = this.cipher.encryptMessage(vaultKeypair.publicJwk, vaultKeypair.privateJwk, JSON.stringify({}));
2081
2126
  const sha256 = this.cipher.hashJSON({});
2082
- const groupVault = {
2127
+ const vault = {
2083
2128
  version,
2084
2129
  publicJwk: vaultKeypair.publicJwk,
2085
2130
  salt,
@@ -2089,46 +2134,46 @@ export default class Keymaster {
2089
2134
  items,
2090
2135
  sha256,
2091
2136
  };
2092
- await this.addMemberKey(groupVault, id.did, vaultKeypair.privateJwk);
2093
- return this.createAsset({ groupVault }, options);
2137
+ await this.addMemberKey(vault, id.did, vaultKeypair.privateJwk);
2138
+ return this.createAsset({ vault }, options);
2094
2139
  }
2095
- async getGroupVault(groupVaultId, options) {
2096
- const asset = await this.resolveAsset(groupVaultId, options);
2097
- if (!asset.groupVault) {
2098
- throw new InvalidParameterError('groupVaultId');
2140
+ async getVault(vaultId, options) {
2141
+ const asset = await this.resolveAsset(vaultId, options);
2142
+ if (!asset.vault) {
2143
+ throw new InvalidParameterError('vaultId');
2099
2144
  }
2100
- return asset.groupVault;
2145
+ return asset.vault;
2101
2146
  }
2102
- async testGroupVault(id, options) {
2147
+ async testVault(id, options) {
2103
2148
  try {
2104
- const groupVault = await this.getGroupVault(id, options);
2105
- return groupVault !== null;
2149
+ const vault = await this.getVault(id, options);
2150
+ return vault !== null;
2106
2151
  }
2107
2152
  catch (error) {
2108
2153
  return false;
2109
2154
  }
2110
2155
  }
2111
- generateSaltedId(groupVault, memberDID) {
2112
- if (!groupVault.version) {
2113
- return this.cipher.hashMessage(groupVault.salt + memberDID);
2156
+ generateSaltedId(vault, memberDID) {
2157
+ if (!vault.version) {
2158
+ return this.cipher.hashMessage(vault.salt + memberDID);
2114
2159
  }
2115
2160
  const suffix = memberDID.split(':').pop();
2116
- return this.cipher.hashMessage(groupVault.salt + suffix);
2161
+ return this.cipher.hashMessage(vault.salt + suffix);
2117
2162
  }
2118
- async decryptGroupVault(groupVault) {
2163
+ async decryptVault(vault) {
2119
2164
  const wallet = await this.loadWallet();
2120
2165
  const id = await this.fetchIdInfo();
2121
- const myMemberId = this.generateSaltedId(groupVault, id.did);
2122
- const myVaultKey = groupVault.keys[myMemberId];
2166
+ const myMemberId = this.generateSaltedId(vault, id.did);
2167
+ const myVaultKey = vault.keys[myMemberId];
2123
2168
  if (!myVaultKey) {
2124
- throw new KeymasterError('No access to group vault');
2169
+ throw new KeymasterError('No access to vault');
2125
2170
  }
2126
- const privKeyJSON = await this.decryptWithDerivedKeys(wallet, id, groupVault.publicJwk, myVaultKey);
2171
+ const privKeyJSON = await this.decryptWithDerivedKeys(wallet, id, vault.publicJwk, myVaultKey);
2127
2172
  const privateJwk = JSON.parse(privKeyJSON);
2128
2173
  let config = {};
2129
2174
  let isOwner = false;
2130
2175
  try {
2131
- const configJSON = await this.decryptWithDerivedKeys(wallet, id, groupVault.publicJwk, groupVault.config);
2176
+ const configJSON = await this.decryptWithDerivedKeys(wallet, id, vault.publicJwk, vault.config);
2132
2177
  config = JSON.parse(configJSON);
2133
2178
  isOwner = true;
2134
2179
  }
@@ -2138,7 +2183,7 @@ export default class Keymaster {
2138
2183
  let members = {};
2139
2184
  if (config.secretMembers) {
2140
2185
  try {
2141
- const membersJSON = await this.decryptWithDerivedKeys(wallet, id, groupVault.publicJwk, groupVault.members);
2186
+ const membersJSON = await this.decryptWithDerivedKeys(wallet, id, vault.publicJwk, vault.members);
2142
2187
  members = JSON.parse(membersJSON);
2143
2188
  }
2144
2189
  catch (error) {
@@ -2146,13 +2191,13 @@ export default class Keymaster {
2146
2191
  }
2147
2192
  else {
2148
2193
  try {
2149
- const membersJSON = this.cipher.decryptMessage(groupVault.publicJwk, privateJwk, groupVault.members);
2194
+ const membersJSON = this.cipher.decryptMessage(vault.publicJwk, privateJwk, vault.members);
2150
2195
  members = JSON.parse(membersJSON);
2151
2196
  }
2152
2197
  catch (error) {
2153
2198
  }
2154
2199
  }
2155
- const itemsJSON = this.cipher.decryptMessage(groupVault.publicJwk, privateJwk, groupVault.items);
2200
+ const itemsJSON = this.cipher.decryptMessage(vault.publicJwk, privateJwk, vault.items);
2156
2201
  const items = JSON.parse(itemsJSON);
2157
2202
  return {
2158
2203
  isOwner,
@@ -2162,7 +2207,7 @@ export default class Keymaster {
2162
2207
  items,
2163
2208
  };
2164
2209
  }
2165
- async checkGroupVaultOwner(vaultId) {
2210
+ async checkVaultOwner(vaultId) {
2166
2211
  const id = await this.fetchIdInfo();
2167
2212
  const vaultDoc = await this.resolveDID(vaultId);
2168
2213
  const controller = vaultDoc.didDocument?.controller;
@@ -2171,30 +2216,30 @@ export default class Keymaster {
2171
2216
  }
2172
2217
  return controller;
2173
2218
  }
2174
- async addMemberKey(groupVault, memberDID, privateJwk) {
2219
+ async addMemberKey(vault, memberDID, privateJwk) {
2175
2220
  const memberDoc = await this.resolveDID(memberDID, { confirm: true });
2176
2221
  const memberPublicJwk = this.getPublicKeyJwk(memberDoc);
2177
2222
  const memberKey = this.cipher.encryptMessage(memberPublicJwk, privateJwk, JSON.stringify(privateJwk));
2178
- const memberKeyId = this.generateSaltedId(groupVault, memberDID);
2179
- groupVault.keys[memberKeyId] = memberKey;
2223
+ const memberKeyId = this.generateSaltedId(vault, memberDID);
2224
+ vault.keys[memberKeyId] = memberKey;
2180
2225
  }
2181
- async checkVaultVersion(vaultId, groupVault) {
2182
- if (groupVault.version === 1) {
2226
+ async checkVaultVersion(vaultId, vault) {
2227
+ if (vault.version === 1) {
2183
2228
  return;
2184
2229
  }
2185
- if (!groupVault.version) {
2230
+ if (!vault.version) {
2186
2231
  const id = await this.fetchIdInfo();
2187
- const { privateJwk, members } = await this.decryptGroupVault(groupVault);
2188
- groupVault.version = 1;
2189
- groupVault.keys = {};
2190
- await this.addMemberKey(groupVault, id.did, privateJwk);
2232
+ const { privateJwk, members } = await this.decryptVault(vault);
2233
+ vault.version = 1;
2234
+ vault.keys = {};
2235
+ await this.addMemberKey(vault, id.did, privateJwk);
2191
2236
  for (const memberDID of Object.keys(members)) {
2192
- await this.addMemberKey(groupVault, memberDID, privateJwk);
2237
+ await this.addMemberKey(vault, memberDID, privateJwk);
2193
2238
  }
2194
- await this.updateAsset(vaultId, { groupVault });
2239
+ await this.updateAsset(vaultId, { vault });
2195
2240
  return;
2196
2241
  }
2197
- throw new KeymasterError('Unsupported group vault version');
2242
+ throw new KeymasterError('Unsupported vault version');
2198
2243
  }
2199
2244
  getAgentDID(doc) {
2200
2245
  if (doc.didDocumentRegistration?.type !== 'agent') {
@@ -2206,11 +2251,11 @@ export default class Keymaster {
2206
2251
  }
2207
2252
  return did;
2208
2253
  }
2209
- async addGroupVaultMember(vaultId, memberId) {
2210
- const owner = await this.checkGroupVaultOwner(vaultId);
2254
+ async addVaultMember(vaultId, memberId) {
2255
+ const owner = await this.checkVaultOwner(vaultId);
2211
2256
  const idKeypair = await this.fetchKeyPair();
2212
- const groupVault = await this.getGroupVault(vaultId);
2213
- const { privateJwk, config, members } = await this.decryptGroupVault(groupVault);
2257
+ const vault = await this.getVault(vaultId);
2258
+ const { privateJwk, config, members } = await this.decryptVault(vault);
2214
2259
  const memberDoc = await this.resolveDID(memberId, { confirm: true });
2215
2260
  const memberDID = this.getAgentDID(memberDoc);
2216
2261
  // Don't allow adding the vault owner
@@ -2218,16 +2263,16 @@ export default class Keymaster {
2218
2263
  return false;
2219
2264
  }
2220
2265
  members[memberDID] = { added: new Date().toISOString() };
2221
- const publicJwk = config.secretMembers ? idKeypair.publicJwk : groupVault.publicJwk;
2222
- groupVault.members = this.cipher.encryptMessage(publicJwk, privateJwk, JSON.stringify(members));
2223
- await this.addMemberKey(groupVault, memberDID, privateJwk);
2224
- return this.updateAsset(vaultId, { groupVault });
2266
+ const publicJwk = config.secretMembers ? idKeypair.publicJwk : vault.publicJwk;
2267
+ vault.members = this.cipher.encryptMessage(publicJwk, privateJwk, JSON.stringify(members));
2268
+ await this.addMemberKey(vault, memberDID, privateJwk);
2269
+ return this.updateAsset(vaultId, { vault });
2225
2270
  }
2226
- async removeGroupVaultMember(vaultId, memberId) {
2227
- const owner = await this.checkGroupVaultOwner(vaultId);
2271
+ async removeVaultMember(vaultId, memberId) {
2272
+ const owner = await this.checkVaultOwner(vaultId);
2228
2273
  const idKeypair = await this.fetchKeyPair();
2229
- const groupVault = await this.getGroupVault(vaultId);
2230
- const { privateJwk, config, members } = await this.decryptGroupVault(groupVault);
2274
+ const vault = await this.getVault(vaultId);
2275
+ const { privateJwk, config, members } = await this.decryptVault(vault);
2231
2276
  const memberDoc = await this.resolveDID(memberId, { confirm: true });
2232
2277
  const memberDID = this.getAgentDID(memberDoc);
2233
2278
  // Don't allow removing the vault owner
@@ -2235,26 +2280,26 @@ export default class Keymaster {
2235
2280
  return false;
2236
2281
  }
2237
2282
  delete members[memberDID];
2238
- const publicJwk = config.secretMembers ? idKeypair.publicJwk : groupVault.publicJwk;
2239
- groupVault.members = this.cipher.encryptMessage(publicJwk, privateJwk, JSON.stringify(members));
2240
- const memberKeyId = this.generateSaltedId(groupVault, memberDID);
2241
- delete groupVault.keys[memberKeyId];
2242
- return this.updateAsset(vaultId, { groupVault });
2243
- }
2244
- async listGroupVaultMembers(vaultId) {
2245
- const groupVault = await this.getGroupVault(vaultId);
2246
- const { members, isOwner } = await this.decryptGroupVault(groupVault);
2283
+ const publicJwk = config.secretMembers ? idKeypair.publicJwk : vault.publicJwk;
2284
+ vault.members = this.cipher.encryptMessage(publicJwk, privateJwk, JSON.stringify(members));
2285
+ const memberKeyId = this.generateSaltedId(vault, memberDID);
2286
+ delete vault.keys[memberKeyId];
2287
+ return this.updateAsset(vaultId, { vault });
2288
+ }
2289
+ async listVaultMembers(vaultId) {
2290
+ const vault = await this.getVault(vaultId);
2291
+ const { members, isOwner } = await this.decryptVault(vault);
2247
2292
  if (isOwner) {
2248
- await this.checkVaultVersion(vaultId, groupVault);
2293
+ await this.checkVaultVersion(vaultId, vault);
2249
2294
  }
2250
2295
  return members;
2251
2296
  }
2252
- async addGroupVaultItem(vaultId, name, buffer) {
2253
- await this.checkGroupVaultOwner(vaultId);
2254
- const groupVault = await this.getGroupVault(vaultId);
2255
- const { privateJwk, items } = await this.decryptGroupVault(groupVault);
2297
+ async addVaultItem(vaultId, name, buffer) {
2298
+ await this.checkVaultOwner(vaultId);
2299
+ const vault = await this.getVault(vaultId);
2300
+ const { privateJwk, items } = await this.decryptVault(vault);
2256
2301
  const validName = this.validateName(name);
2257
- const encryptedData = this.cipher.encryptBytes(groupVault.publicJwk, privateJwk, buffer);
2302
+ const encryptedData = this.cipher.encryptBytes(vault.publicJwk, privateJwk, buffer);
2258
2303
  const cid = await this.gatekeeper.addText(encryptedData);
2259
2304
  const sha256 = this.cipher.hashMessage(buffer);
2260
2305
  const type = await this.getMimeType(buffer);
@@ -2267,32 +2312,32 @@ export default class Keymaster {
2267
2312
  added: new Date().toISOString(),
2268
2313
  data,
2269
2314
  };
2270
- groupVault.items = this.cipher.encryptMessage(groupVault.publicJwk, privateJwk, JSON.stringify(items));
2271
- groupVault.sha256 = this.cipher.hashJSON(items);
2272
- return this.updateAsset(vaultId, { groupVault });
2273
- }
2274
- async removeGroupVaultItem(vaultId, name) {
2275
- await this.checkGroupVaultOwner(vaultId);
2276
- const groupVault = await this.getGroupVault(vaultId);
2277
- const { privateJwk, items } = await this.decryptGroupVault(groupVault);
2315
+ vault.items = this.cipher.encryptMessage(vault.publicJwk, privateJwk, JSON.stringify(items));
2316
+ vault.sha256 = this.cipher.hashJSON(items);
2317
+ return this.updateAsset(vaultId, { vault });
2318
+ }
2319
+ async removeVaultItem(vaultId, name) {
2320
+ await this.checkVaultOwner(vaultId);
2321
+ const vault = await this.getVault(vaultId);
2322
+ const { privateJwk, items } = await this.decryptVault(vault);
2278
2323
  delete items[name];
2279
- groupVault.items = this.cipher.encryptMessage(groupVault.publicJwk, privateJwk, JSON.stringify(items));
2280
- groupVault.sha256 = this.cipher.hashJSON(items);
2281
- return this.updateAsset(vaultId, { groupVault });
2324
+ vault.items = this.cipher.encryptMessage(vault.publicJwk, privateJwk, JSON.stringify(items));
2325
+ vault.sha256 = this.cipher.hashJSON(items);
2326
+ return this.updateAsset(vaultId, { vault });
2282
2327
  }
2283
- async listGroupVaultItems(vaultId, options) {
2284
- const groupVault = await this.getGroupVault(vaultId, options);
2285
- const { items } = await this.decryptGroupVault(groupVault);
2328
+ async listVaultItems(vaultId, options) {
2329
+ const vault = await this.getVault(vaultId, options);
2330
+ const { items } = await this.decryptVault(vault);
2286
2331
  return items;
2287
2332
  }
2288
- async getGroupVaultItem(vaultId, name, options) {
2333
+ async getVaultItem(vaultId, name, options) {
2289
2334
  try {
2290
- const groupVault = await this.getGroupVault(vaultId, options);
2291
- const { privateJwk, items } = await this.decryptGroupVault(groupVault);
2335
+ const vault = await this.getVault(vaultId, options);
2336
+ const { privateJwk, items } = await this.decryptVault(vault);
2292
2337
  if (items[name]) {
2293
2338
  const encryptedData = items[name].data || await this.gatekeeper.getText(items[name].cid);
2294
2339
  if (encryptedData) {
2295
- const bytes = this.cipher.decryptBytes(groupVault.publicJwk, privateJwk, encryptedData);
2340
+ const bytes = this.cipher.decryptBytes(vault.publicJwk, privateJwk, encryptedData);
2296
2341
  return Buffer.from(bytes);
2297
2342
  }
2298
2343
  }
@@ -2421,28 +2466,28 @@ export default class Keymaster {
2421
2466
  }
2422
2467
  async createDmail(message, options = {}) {
2423
2468
  const dmail = await this.verifyDmail(message);
2424
- const did = await this.createGroupVault(options);
2469
+ const did = await this.createVault(options);
2425
2470
  for (const toDID of dmail.to) {
2426
- await this.addGroupVaultMember(did, toDID);
2471
+ await this.addVaultMember(did, toDID);
2427
2472
  }
2428
2473
  for (const ccDID of dmail.cc) {
2429
- await this.addGroupVaultMember(did, ccDID);
2474
+ await this.addVaultMember(did, ccDID);
2430
2475
  }
2431
2476
  const buffer = Buffer.from(JSON.stringify({ dmail }), 'utf-8');
2432
- await this.addGroupVaultItem(did, DmailTags.DMAIL, buffer);
2477
+ await this.addVaultItem(did, DmailTags.DMAIL, buffer);
2433
2478
  await this.fileDmail(did, [DmailTags.DRAFT]);
2434
2479
  return did;
2435
2480
  }
2436
2481
  async updateDmail(did, message) {
2437
2482
  const dmail = await this.verifyDmail(message);
2438
2483
  for (const toDID of dmail.to) {
2439
- await this.addGroupVaultMember(did, toDID);
2484
+ await this.addVaultMember(did, toDID);
2440
2485
  }
2441
2486
  for (const ccDID of dmail.cc) {
2442
- await this.addGroupVaultMember(did, ccDID);
2487
+ await this.addVaultMember(did, ccDID);
2443
2488
  }
2444
2489
  const buffer = Buffer.from(JSON.stringify({ dmail }), 'utf-8');
2445
- return this.addGroupVaultItem(did, DmailTags.DMAIL, buffer);
2490
+ return this.addVaultItem(did, DmailTags.DMAIL, buffer);
2446
2491
  }
2447
2492
  async sendDmail(did) {
2448
2493
  const dmail = await this.getDmailMessage(did);
@@ -2462,11 +2507,11 @@ export default class Keymaster {
2462
2507
  return notice;
2463
2508
  }
2464
2509
  async getDmailMessage(did, options) {
2465
- const isGroupVault = await this.testGroupVault(did, options);
2466
- if (!isGroupVault) {
2510
+ const isVault = await this.testVault(did, options);
2511
+ if (!isVault) {
2467
2512
  return null;
2468
2513
  }
2469
- const buffer = await this.getGroupVaultItem(did, DmailTags.DMAIL, options);
2514
+ const buffer = await this.getVaultItem(did, DmailTags.DMAIL, options);
2470
2515
  if (!buffer) {
2471
2516
  return null;
2472
2517
  }
@@ -2479,7 +2524,7 @@ export default class Keymaster {
2479
2524
  }
2480
2525
  }
2481
2526
  async listDmailAttachments(did, options) {
2482
- let items = await this.listGroupVaultItems(did, options);
2527
+ let items = await this.listVaultItems(did, options);
2483
2528
  delete items[DmailTags.DMAIL]; // Remove the dmail item itself from attachments
2484
2529
  return items;
2485
2530
  }
@@ -2487,16 +2532,16 @@ export default class Keymaster {
2487
2532
  if (name === DmailTags.DMAIL) {
2488
2533
  throw new InvalidParameterError('Cannot add attachment with reserved name "dmail"');
2489
2534
  }
2490
- return this.addGroupVaultItem(did, name, buffer);
2535
+ return this.addVaultItem(did, name, buffer);
2491
2536
  }
2492
2537
  async removeDmailAttachment(did, name) {
2493
2538
  if (name === DmailTags.DMAIL) {
2494
2539
  throw new InvalidParameterError('Cannot remove attachment with reserved name "dmail"');
2495
2540
  }
2496
- return this.removeGroupVaultItem(did, name);
2541
+ return this.removeVaultItem(did, name);
2497
2542
  }
2498
2543
  async getDmailAttachment(did, name) {
2499
- return this.getGroupVaultItem(did, name);
2544
+ return this.getVaultItem(did, name);
2500
2545
  }
2501
2546
  async importDmail(did) {
2502
2547
  const dmail = await this.getDmailMessage(did);