@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.
- package/dist/cjs/keymaster-client.cjs +26 -26
- package/dist/cjs/keymaster.cjs +277 -208
- package/dist/esm/keymaster-client.js +26 -26
- package/dist/esm/keymaster-client.js.map +1 -1
- package/dist/esm/keymaster.js +218 -173
- package/dist/esm/keymaster.js.map +1 -1
- package/dist/types/keymaster-client.d.ts +16 -14
- package/dist/types/keymaster.d.ts +22 -20
- package/dist/types/types.d.ts +26 -25
- package/package.json +2 -2
package/dist/cjs/keymaster.cjs
CHANGED
|
@@ -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
|
|
1390
|
+
const signatureHex = this.cipher.signHash(msgHash, keypair.privateJwk);
|
|
1358
1391
|
const signed = {
|
|
1359
1392
|
...operation,
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
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
|
|
1419
|
+
const signatureHex = this.cipher.signHash(msgHash, keypair.privateJwk);
|
|
1385
1420
|
const signed = {
|
|
1386
1421
|
...operation,
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
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
|
|
1452
|
+
const signatureHex = this.cipher.signHash(msgHash, keypair.privateJwk);
|
|
1417
1453
|
const signed = {
|
|
1418
1454
|
...operation,
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
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.
|
|
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
|
|
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('
|
|
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
|
|
1845
|
+
const signatureHex = this.cipher.signHash(msgHash, keypair.privateJwk);
|
|
1846
|
+
const proofValue = hexToBase64url(signatureHex);
|
|
1806
1847
|
return {
|
|
1807
1848
|
...obj,
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
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
|
|
1821
|
-
if (!obj?.
|
|
1862
|
+
async verifyProof(obj) {
|
|
1863
|
+
if (!obj?.proof) {
|
|
1822
1864
|
return false;
|
|
1823
1865
|
}
|
|
1824
|
-
const {
|
|
1825
|
-
if (
|
|
1866
|
+
const { proof } = obj;
|
|
1867
|
+
if (proof.type !== "EcdsaSecp256k1Signature2019") {
|
|
1826
1868
|
return false;
|
|
1827
1869
|
}
|
|
1828
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
-
//
|
|
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
|
|
2138
|
+
const signatureHex = this.cipher.signHash(msgHash, keypair.privateJwk);
|
|
2090
2139
|
const signed = {
|
|
2091
2140
|
...operation,
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
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
|
|
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,
|
|
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.
|
|
2163
|
-
throw new InvalidDIDError('didDocumentData missing
|
|
2213
|
+
if (!docData.backupStore) {
|
|
2214
|
+
throw new InvalidDIDError('didDocumentData missing backupStore');
|
|
2164
2215
|
}
|
|
2165
|
-
const
|
|
2166
|
-
if (typeof
|
|
2167
|
-
throw new InvalidDIDError('backup not found in
|
|
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,
|
|
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(
|
|
2264
|
-
let { validFrom, validUntil,
|
|
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
|
-
|
|
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",
|
|
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.
|
|
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.
|
|
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.
|
|
2334
|
-
const signed = await this.
|
|
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
|
|
2429
|
-
vc.
|
|
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.
|
|
2488
|
-
// Wrong
|
|
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.
|
|
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.
|
|
2622
|
-
const schema = vp.
|
|
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
|
|
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
|
|
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(
|
|
3146
|
-
return this.createAsset({
|
|
3214
|
+
await this.addMemberKey(vault, id.did, vaultKeypair.privateJwk);
|
|
3215
|
+
return this.createAsset({ vault }, options);
|
|
3147
3216
|
}
|
|
3148
|
-
async
|
|
3149
|
-
const asset = await this.resolveAsset(
|
|
3150
|
-
if (!asset.
|
|
3151
|
-
throw new InvalidParameterError('
|
|
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.
|
|
3222
|
+
return asset.vault;
|
|
3154
3223
|
}
|
|
3155
|
-
async
|
|
3224
|
+
async testVault(id, options) {
|
|
3156
3225
|
try {
|
|
3157
|
-
const
|
|
3158
|
-
return
|
|
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(
|
|
3165
|
-
if (!
|
|
3166
|
-
return this.cipher.hashMessage(
|
|
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(
|
|
3238
|
+
return this.cipher.hashMessage(vault.salt + suffix);
|
|
3170
3239
|
}
|
|
3171
|
-
async
|
|
3240
|
+
async decryptVault(vault) {
|
|
3172
3241
|
const wallet = await this.loadWallet();
|
|
3173
3242
|
const id = await this.fetchIdInfo();
|
|
3174
|
-
const myMemberId = this.generateSaltedId(
|
|
3175
|
-
const myVaultKey =
|
|
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
|
|
3246
|
+
throw new KeymasterError('No access to vault');
|
|
3178
3247
|
}
|
|
3179
|
-
const privKeyJSON = await this.decryptWithDerivedKeys(wallet, id,
|
|
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,
|
|
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,
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
3232
|
-
|
|
3300
|
+
const memberKeyId = this.generateSaltedId(vault, memberDID);
|
|
3301
|
+
vault.keys[memberKeyId] = memberKey;
|
|
3233
3302
|
}
|
|
3234
|
-
async checkVaultVersion(vaultId,
|
|
3235
|
-
if (
|
|
3303
|
+
async checkVaultVersion(vaultId, vault) {
|
|
3304
|
+
if (vault.version === 1) {
|
|
3236
3305
|
return;
|
|
3237
3306
|
}
|
|
3238
|
-
if (!
|
|
3307
|
+
if (!vault.version) {
|
|
3239
3308
|
const id = await this.fetchIdInfo();
|
|
3240
|
-
const { privateJwk, members } = await this.
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
await this.addMemberKey(
|
|
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(
|
|
3314
|
+
await this.addMemberKey(vault, memberDID, privateJwk);
|
|
3246
3315
|
}
|
|
3247
|
-
await this.updateAsset(vaultId, {
|
|
3316
|
+
await this.updateAsset(vaultId, { vault });
|
|
3248
3317
|
return;
|
|
3249
3318
|
}
|
|
3250
|
-
throw new KeymasterError('Unsupported
|
|
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
|
|
3263
|
-
const owner = await this.
|
|
3331
|
+
async addVaultMember(vaultId, memberId) {
|
|
3332
|
+
const owner = await this.checkVaultOwner(vaultId);
|
|
3264
3333
|
const idKeypair = await this.fetchKeyPair();
|
|
3265
|
-
const
|
|
3266
|
-
const { privateJwk, config, members } = await this.
|
|
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 :
|
|
3275
|
-
|
|
3276
|
-
await this.addMemberKey(
|
|
3277
|
-
return this.updateAsset(vaultId, {
|
|
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
|
|
3280
|
-
const owner = await this.
|
|
3348
|
+
async removeVaultMember(vaultId, memberId) {
|
|
3349
|
+
const owner = await this.checkVaultOwner(vaultId);
|
|
3281
3350
|
const idKeypair = await this.fetchKeyPair();
|
|
3282
|
-
const
|
|
3283
|
-
const { privateJwk, config, members } = await this.
|
|
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 :
|
|
3292
|
-
|
|
3293
|
-
const memberKeyId = this.generateSaltedId(
|
|
3294
|
-
delete
|
|
3295
|
-
return this.updateAsset(vaultId, {
|
|
3296
|
-
}
|
|
3297
|
-
async
|
|
3298
|
-
const
|
|
3299
|
-
const { members, isOwner } = await this.
|
|
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,
|
|
3370
|
+
await this.checkVaultVersion(vaultId, vault);
|
|
3302
3371
|
}
|
|
3303
3372
|
return members;
|
|
3304
3373
|
}
|
|
3305
|
-
async
|
|
3306
|
-
await this.
|
|
3307
|
-
const
|
|
3308
|
-
const { privateJwk, items } = await this.
|
|
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(
|
|
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
|
-
|
|
3324
|
-
|
|
3325
|
-
return this.updateAsset(vaultId, {
|
|
3326
|
-
}
|
|
3327
|
-
async
|
|
3328
|
-
await this.
|
|
3329
|
-
const
|
|
3330
|
-
const { privateJwk, items } = await this.
|
|
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
|
-
|
|
3333
|
-
|
|
3334
|
-
return this.updateAsset(vaultId, {
|
|
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
|
|
3337
|
-
const
|
|
3338
|
-
const { items } = await this.
|
|
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
|
|
3410
|
+
async getVaultItem(vaultId, name, options) {
|
|
3342
3411
|
try {
|
|
3343
|
-
const
|
|
3344
|
-
const { privateJwk, items } = await this.
|
|
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(
|
|
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.
|
|
3546
|
+
const did = await this.createVault(options);
|
|
3478
3547
|
for (const toDID of dmail.to) {
|
|
3479
|
-
await this.
|
|
3548
|
+
await this.addVaultMember(did, toDID);
|
|
3480
3549
|
}
|
|
3481
3550
|
for (const ccDID of dmail.cc) {
|
|
3482
|
-
await this.
|
|
3551
|
+
await this.addVaultMember(did, ccDID);
|
|
3483
3552
|
}
|
|
3484
3553
|
const buffer = Buffer.from(JSON.stringify({ dmail }), 'utf-8');
|
|
3485
|
-
await this.
|
|
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.
|
|
3561
|
+
await this.addVaultMember(did, toDID);
|
|
3493
3562
|
}
|
|
3494
3563
|
for (const ccDID of dmail.cc) {
|
|
3495
|
-
await this.
|
|
3564
|
+
await this.addVaultMember(did, ccDID);
|
|
3496
3565
|
}
|
|
3497
3566
|
const buffer = Buffer.from(JSON.stringify({ dmail }), 'utf-8');
|
|
3498
|
-
return this.
|
|
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
|
|
3519
|
-
if (!
|
|
3587
|
+
const isVault = await this.testVault(did, options);
|
|
3588
|
+
if (!isVault) {
|
|
3520
3589
|
return null;
|
|
3521
3590
|
}
|
|
3522
|
-
const buffer = await this.
|
|
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.
|
|
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.
|
|
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.
|
|
3618
|
+
return this.removeVaultItem(did, name);
|
|
3550
3619
|
}
|
|
3551
3620
|
async getDmailAttachment(did, name) {
|
|
3552
|
-
return this.
|
|
3621
|
+
return this.getVaultItem(did, name);
|
|
3553
3622
|
}
|
|
3554
3623
|
async importDmail(did) {
|
|
3555
3624
|
const dmail = await this.getDmailMessage(did);
|