@twin.org/identity-connector-entity-storage 0.0.1-next.3 → 0.0.1-next.31
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/index.cjs +250 -209
- package/dist/esm/index.mjs +254 -214
- package/dist/types/entityStorageIdentityConnector.d.ts +24 -39
- package/dist/types/entityStorageIdentityProfileConnector.d.ts +4 -6
- package/dist/types/entityStorageIdentityResolverConnector.d.ts +28 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/models/IEntityStorageIdentityConnectorConstructorOptions.d.ts +6 -0
- package/dist/types/models/IEntityStorageIdentityProfileConnectorConstructorOptions.d.ts +10 -0
- package/dist/types/models/IEntityStorageIdentityResolverConnectorConstructorOptions.d.ts +15 -0
- package/docs/changelog.md +1 -1
- package/docs/reference/classes/EntityStorageIdentityConnector.md +140 -154
- package/docs/reference/classes/EntityStorageIdentityProfileConnector.md +56 -46
- package/docs/reference/classes/EntityStorageIdentityResolverConnector.md +77 -0
- package/docs/reference/functions/initSchema.md +7 -3
- package/docs/reference/index.md +7 -0
- package/docs/reference/interfaces/IEntityStorageIdentityConnectorConstructorOptions.md +43 -0
- package/docs/reference/interfaces/IEntityStorageIdentityProfileConnectorConstructorOptions.md +17 -0
- package/docs/reference/interfaces/IEntityStorageIdentityResolverConnectorConstructorOptions.md +35 -0
- package/locales/en.json +9 -4
- package/package.json +5 -35
package/dist/cjs/index.cjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var entity = require('@twin.org/entity');
|
|
4
4
|
var core = require('@twin.org/core');
|
|
5
5
|
var crypto = require('@twin.org/crypto');
|
|
6
|
+
var dataJsonLd = require('@twin.org/data-json-ld');
|
|
6
7
|
var entityStorageModels = require('@twin.org/entity-storage-models');
|
|
7
8
|
var identityModels = require('@twin.org/identity-models');
|
|
8
9
|
var standardsW3cDid = require('@twin.org/standards-w3c-did');
|
|
@@ -118,14 +119,34 @@ class EntityStorageIdentityConnector {
|
|
|
118
119
|
_vaultConnector;
|
|
119
120
|
/**
|
|
120
121
|
* Create a new instance of EntityStorageIdentityConnector.
|
|
121
|
-
* @param options The
|
|
122
|
-
* @param options.didDocumentEntityStorageType The entity storage for the did documents, defaults to "identity-document".
|
|
123
|
-
* @param options.vaultConnectorType The vault for the private keys, defaults to "vault".
|
|
122
|
+
* @param options The options for the identity connector.
|
|
124
123
|
*/
|
|
125
124
|
constructor(options) {
|
|
126
125
|
this._didDocumentEntityStorage = entityStorageModels.EntityStorageConnectorFactory.get(options?.didDocumentEntityStorageType ?? "identity-document");
|
|
127
126
|
this._vaultConnector = vaultModels.VaultConnectorFactory.get(options?.vaultConnectorType ?? "vault");
|
|
128
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Build the key name to access the specified key in the vault.
|
|
130
|
+
* @param identity The identity of the user to access the vault keys.
|
|
131
|
+
* @returns The vault key.
|
|
132
|
+
* @internal
|
|
133
|
+
*/
|
|
134
|
+
static buildVaultKey(identity, key) {
|
|
135
|
+
return `${identity}/${key}`;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Verify the document in storage.
|
|
139
|
+
* @param didDocument The did document that was stored.
|
|
140
|
+
* @internal
|
|
141
|
+
*/
|
|
142
|
+
static async verifyDocument(didDocument, vaultConnector) {
|
|
143
|
+
const stringifiedDocument = core.JsonHelper.canonicalize(didDocument.document);
|
|
144
|
+
const docBytes = core.Converter.utf8ToBytes(stringifiedDocument);
|
|
145
|
+
const verified = await vaultConnector.verify(EntityStorageIdentityConnector.buildVaultKey(didDocument.id, "did"), docBytes, core.Converter.base64ToBytes(didDocument.signature));
|
|
146
|
+
if (!verified) {
|
|
147
|
+
throw new core.GeneralError("EntityStorageIdentityResolverConnector", "signatureVerificationFailed");
|
|
148
|
+
}
|
|
149
|
+
}
|
|
129
150
|
/**
|
|
130
151
|
* Create a new document.
|
|
131
152
|
* @param controller The controller of the identity who can make changes.
|
|
@@ -135,10 +156,11 @@ class EntityStorageIdentityConnector {
|
|
|
135
156
|
core.Guards.stringValue(this.CLASS_NAME, "controller", controller);
|
|
136
157
|
try {
|
|
137
158
|
const did = `did:${EntityStorageIdentityConnector.NAMESPACE}:${core.Converter.bytesToHex(core.RandomHelper.generate(32), true)}`;
|
|
138
|
-
await this._vaultConnector.createKey(
|
|
159
|
+
await this._vaultConnector.createKey(EntityStorageIdentityConnector.buildVaultKey(did, "did"), vaultModels.VaultKeyType.Ed25519);
|
|
139
160
|
const bitString = new core.BitString(EntityStorageIdentityConnector._REVOCATION_BITS_SIZE);
|
|
140
161
|
const compressed = await core.Compression.compress(bitString.getBits(), core.CompressionType.Gzip);
|
|
141
162
|
const didDocument = {
|
|
163
|
+
"@context": standardsW3cDid.DidContexts.Context,
|
|
142
164
|
id: did,
|
|
143
165
|
service: [
|
|
144
166
|
{
|
|
@@ -155,26 +177,6 @@ class EntityStorageIdentityConnector {
|
|
|
155
177
|
throw new core.GeneralError(this.CLASS_NAME, "createDocumentFailed", undefined, error);
|
|
156
178
|
}
|
|
157
179
|
}
|
|
158
|
-
/**
|
|
159
|
-
* Resolve a document from its id.
|
|
160
|
-
* @param documentId The id of the document to resolve.
|
|
161
|
-
* @returns The resolved document.
|
|
162
|
-
* @throws NotFoundError if the id can not be resolved.
|
|
163
|
-
*/
|
|
164
|
-
async resolveDocument(documentId) {
|
|
165
|
-
core.Guards.stringValue(this.CLASS_NAME, "documentId", documentId);
|
|
166
|
-
try {
|
|
167
|
-
const didIdentityDocument = await this._didDocumentEntityStorage.get(documentId);
|
|
168
|
-
if (core.Is.undefined(didIdentityDocument)) {
|
|
169
|
-
throw new core.NotFoundError(this.CLASS_NAME, "documentNotFound", documentId);
|
|
170
|
-
}
|
|
171
|
-
await this.verifyDocument(didIdentityDocument);
|
|
172
|
-
return didIdentityDocument.document;
|
|
173
|
-
}
|
|
174
|
-
catch (error) {
|
|
175
|
-
throw new core.GeneralError(this.CLASS_NAME, "resolveDocumentFailed", undefined, error);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
180
|
/**
|
|
179
181
|
* Add a verification method to the document in JSON Web key Format.
|
|
180
182
|
* @param controller The controller of the identity who can make changes.
|
|
@@ -194,10 +196,10 @@ class EntityStorageIdentityConnector {
|
|
|
194
196
|
if (core.Is.undefined(didIdentityDocument)) {
|
|
195
197
|
throw new core.NotFoundError(this.CLASS_NAME, "documentNotFound", documentId);
|
|
196
198
|
}
|
|
197
|
-
await
|
|
199
|
+
await EntityStorageIdentityConnector.verifyDocument(didIdentityDocument, this._vaultConnector);
|
|
198
200
|
const didDocument = didIdentityDocument.document;
|
|
199
|
-
const tempKeyId = `temp-${core.Converter.bytesToBase64Url(core.RandomHelper.generate(
|
|
200
|
-
const verificationPublicKey = await this._vaultConnector.createKey(
|
|
201
|
+
const tempKeyId = `temp-vm-${core.Converter.bytesToBase64Url(core.RandomHelper.generate(16))}`;
|
|
202
|
+
const verificationPublicKey = await this._vaultConnector.createKey(EntityStorageIdentityConnector.buildVaultKey(didDocument.id, tempKeyId), vaultModels.VaultKeyType.Ed25519);
|
|
201
203
|
const jwkParams = {
|
|
202
204
|
alg: "EdDSA",
|
|
203
205
|
kty: "OKP",
|
|
@@ -206,7 +208,7 @@ class EntityStorageIdentityConnector {
|
|
|
206
208
|
};
|
|
207
209
|
const kid = core.Converter.bytesToBase64Url(crypto.Sha256.sum256(core.Converter.utf8ToBytes(JSON.stringify(jwkParams))));
|
|
208
210
|
const methodId = `${documentId}#${verificationMethodId ?? kid}`;
|
|
209
|
-
await this._vaultConnector.renameKey(
|
|
211
|
+
await this._vaultConnector.renameKey(EntityStorageIdentityConnector.buildVaultKey(didDocument.id, tempKeyId), EntityStorageIdentityConnector.buildVaultKey(didDocument.id, verificationMethodId ?? kid));
|
|
210
212
|
const methods = this.getAllMethods(didDocument);
|
|
211
213
|
const existingMethodIndex = methods.findIndex(m => {
|
|
212
214
|
if (core.Is.string(m.method)) {
|
|
@@ -214,7 +216,7 @@ class EntityStorageIdentityConnector {
|
|
|
214
216
|
}
|
|
215
217
|
return m.method.id === methodId;
|
|
216
218
|
});
|
|
217
|
-
if (existingMethodIndex
|
|
219
|
+
if (existingMethodIndex !== -1) {
|
|
218
220
|
const methodArray = didDocument[methods[existingMethodIndex].arrayKey];
|
|
219
221
|
if (core.Is.array(methodArray)) {
|
|
220
222
|
methodArray.splice(existingMethodIndex, 1);
|
|
@@ -250,15 +252,15 @@ class EntityStorageIdentityConnector {
|
|
|
250
252
|
core.Guards.stringValue(this.CLASS_NAME, "controller", controller);
|
|
251
253
|
core.Guards.stringValue(this.CLASS_NAME, "verificationMethodId", verificationMethodId);
|
|
252
254
|
try {
|
|
253
|
-
const idParts = identityModels.DocumentHelper.
|
|
254
|
-
if (core.Is.empty(idParts.
|
|
255
|
+
const idParts = identityModels.DocumentHelper.parseId(verificationMethodId);
|
|
256
|
+
if (core.Is.empty(idParts.fragment)) {
|
|
255
257
|
throw new core.NotFoundError(this.CLASS_NAME, "missingDid", verificationMethodId);
|
|
256
258
|
}
|
|
257
259
|
const didIdentityDocument = await this._didDocumentEntityStorage.get(idParts.id);
|
|
258
260
|
if (core.Is.undefined(didIdentityDocument)) {
|
|
259
261
|
throw new core.NotFoundError(this.CLASS_NAME, "documentNotFound", idParts.id);
|
|
260
262
|
}
|
|
261
|
-
await
|
|
263
|
+
await EntityStorageIdentityConnector.verifyDocument(didIdentityDocument, this._vaultConnector);
|
|
262
264
|
const didDocument = didIdentityDocument.document;
|
|
263
265
|
const methods = this.getAllMethods(didDocument);
|
|
264
266
|
const existingMethodIndex = methods.findIndex(m => {
|
|
@@ -267,7 +269,7 @@ class EntityStorageIdentityConnector {
|
|
|
267
269
|
}
|
|
268
270
|
return m.method.id === verificationMethodId;
|
|
269
271
|
});
|
|
270
|
-
if (existingMethodIndex
|
|
272
|
+
if (existingMethodIndex !== -1) {
|
|
271
273
|
const methodArray = didDocument[methods[existingMethodIndex].arrayKey];
|
|
272
274
|
if (core.Is.array(methodArray)) {
|
|
273
275
|
methodArray.splice(existingMethodIndex, 1);
|
|
@@ -299,19 +301,29 @@ class EntityStorageIdentityConnector {
|
|
|
299
301
|
core.Guards.stringValue(this.CLASS_NAME, "controller", controller);
|
|
300
302
|
core.Guards.stringValue(this.CLASS_NAME, "documentId", documentId);
|
|
301
303
|
core.Guards.stringValue(this.CLASS_NAME, "serviceId", serviceId);
|
|
302
|
-
core.
|
|
303
|
-
|
|
304
|
+
if (core.Is.array(serviceType)) {
|
|
305
|
+
core.Guards.arrayValue(this.CLASS_NAME, "serviceType", serviceType);
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
core.Guards.stringValue(this.CLASS_NAME, "serviceType", serviceType);
|
|
309
|
+
}
|
|
310
|
+
if (core.Is.array(serviceEndpoint)) {
|
|
311
|
+
core.Guards.arrayValue(this.CLASS_NAME, "serviceEndpoint", serviceEndpoint);
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
core.Guards.stringValue(this.CLASS_NAME, "serviceEndpoint", serviceEndpoint);
|
|
315
|
+
}
|
|
304
316
|
try {
|
|
305
317
|
const didIdentityDocument = await this._didDocumentEntityStorage.get(documentId);
|
|
306
318
|
if (core.Is.undefined(didIdentityDocument)) {
|
|
307
319
|
throw new core.NotFoundError(this.CLASS_NAME, "documentNotFound", documentId);
|
|
308
320
|
}
|
|
309
|
-
await
|
|
321
|
+
await EntityStorageIdentityConnector.verifyDocument(didIdentityDocument, this._vaultConnector);
|
|
310
322
|
const didDocument = didIdentityDocument.document;
|
|
311
323
|
const fullServiceId = serviceId.includes("#") ? serviceId : `${documentId}#${serviceId}`;
|
|
312
324
|
if (core.Is.array(didDocument.service)) {
|
|
313
325
|
const existingServiceIndex = didDocument.service.findIndex(s => s.id === fullServiceId);
|
|
314
|
-
if (existingServiceIndex
|
|
326
|
+
if (existingServiceIndex !== -1) {
|
|
315
327
|
didDocument.service?.splice(existingServiceIndex, 1);
|
|
316
328
|
}
|
|
317
329
|
}
|
|
@@ -340,19 +352,19 @@ class EntityStorageIdentityConnector {
|
|
|
340
352
|
core.Guards.stringValue(this.CLASS_NAME, "controller", controller);
|
|
341
353
|
core.Guards.stringValue(this.CLASS_NAME, "serviceId", serviceId);
|
|
342
354
|
try {
|
|
343
|
-
const idParts = identityModels.DocumentHelper.
|
|
344
|
-
if (core.Is.empty(idParts.
|
|
355
|
+
const idParts = identityModels.DocumentHelper.parseId(serviceId);
|
|
356
|
+
if (core.Is.empty(idParts.fragment)) {
|
|
345
357
|
throw new core.NotFoundError(this.CLASS_NAME, "missingDid", serviceId);
|
|
346
358
|
}
|
|
347
359
|
const didIdentityDocument = await this._didDocumentEntityStorage.get(idParts.id);
|
|
348
360
|
if (core.Is.undefined(didIdentityDocument)) {
|
|
349
361
|
throw new core.NotFoundError(this.CLASS_NAME, "documentNotFound", idParts.id);
|
|
350
362
|
}
|
|
351
|
-
await
|
|
363
|
+
await EntityStorageIdentityConnector.verifyDocument(didIdentityDocument, this._vaultConnector);
|
|
352
364
|
const didDocument = didIdentityDocument.document;
|
|
353
365
|
if (core.Is.array(didDocument.service)) {
|
|
354
366
|
const existingServiceIndex = didDocument.service.findIndex(s => s.id === serviceId);
|
|
355
|
-
if (existingServiceIndex
|
|
367
|
+
if (existingServiceIndex !== -1) {
|
|
356
368
|
didDocument.service?.splice(existingServiceIndex, 1);
|
|
357
369
|
if (didDocument.service?.length === 0) {
|
|
358
370
|
delete didDocument.service;
|
|
@@ -372,51 +384,29 @@ class EntityStorageIdentityConnector {
|
|
|
372
384
|
* Create a verifiable credential for a verification method.
|
|
373
385
|
* @param controller The controller of the identity who can make changes.
|
|
374
386
|
* @param verificationMethodId The verification method id to use.
|
|
375
|
-
* @param
|
|
376
|
-
* @param
|
|
377
|
-
* @param subject The subject data to store for the credential.
|
|
378
|
-
* @param contexts Additional contexts to include in the credential.
|
|
387
|
+
* @param id The id of the credential.
|
|
388
|
+
* @param subject The credential subject to store in the verifiable credential.
|
|
379
389
|
* @param revocationIndex The bitmap revocation index of the credential, if undefined will not have revocation status.
|
|
380
390
|
* @returns The created verifiable credential and its token.
|
|
381
391
|
* @throws NotFoundError if the id can not be resolved.
|
|
382
392
|
*/
|
|
383
|
-
async createVerifiableCredential(controller, verificationMethodId,
|
|
393
|
+
async createVerifiableCredential(controller, verificationMethodId, id, subject, revocationIndex) {
|
|
384
394
|
core.Guards.stringValue(this.CLASS_NAME, "controller", controller);
|
|
385
395
|
core.Guards.stringValue(this.CLASS_NAME, "verificationMethodId", verificationMethodId);
|
|
386
|
-
|
|
387
|
-
core.Guards.stringValue(this.CLASS_NAME, "credentialId", credentialId);
|
|
388
|
-
}
|
|
389
|
-
if (core.Is.array(types)) {
|
|
390
|
-
core.Guards.array(this.CLASS_NAME, "types", types);
|
|
391
|
-
}
|
|
392
|
-
else if (!core.Is.undefined(types)) {
|
|
393
|
-
core.Guards.stringValue(this.CLASS_NAME, "types", types);
|
|
394
|
-
}
|
|
395
|
-
if (core.Is.array(subject)) {
|
|
396
|
-
core.Guards.arrayValue(this.CLASS_NAME, "subject", subject);
|
|
397
|
-
}
|
|
398
|
-
else {
|
|
399
|
-
core.Guards.object(this.CLASS_NAME, "subject", subject);
|
|
400
|
-
}
|
|
401
|
-
if (core.Is.array(contexts)) {
|
|
402
|
-
core.Guards.array(this.CLASS_NAME, "contexts", contexts);
|
|
403
|
-
}
|
|
404
|
-
else if (!core.Is.undefined(contexts)) {
|
|
405
|
-
core.Guards.stringValue(this.CLASS_NAME, "contexts", contexts);
|
|
406
|
-
}
|
|
396
|
+
core.Guards.object(this.CLASS_NAME, "subject", subject);
|
|
407
397
|
if (!core.Is.undefined(revocationIndex)) {
|
|
408
398
|
core.Guards.number(this.CLASS_NAME, "revocationIndex", revocationIndex);
|
|
409
399
|
}
|
|
410
400
|
try {
|
|
411
|
-
const idParts = identityModels.DocumentHelper.
|
|
412
|
-
if (core.Is.empty(idParts.
|
|
401
|
+
const idParts = identityModels.DocumentHelper.parseId(verificationMethodId);
|
|
402
|
+
if (core.Is.empty(idParts.fragment)) {
|
|
413
403
|
throw new core.NotFoundError(this.CLASS_NAME, "missingDid", verificationMethodId);
|
|
414
404
|
}
|
|
415
405
|
const issuerIdentityDocument = await this._didDocumentEntityStorage.get(idParts.id);
|
|
416
406
|
if (core.Is.undefined(issuerIdentityDocument)) {
|
|
417
407
|
throw new core.NotFoundError(this.CLASS_NAME, "documentNotFound", idParts.id);
|
|
418
408
|
}
|
|
419
|
-
await
|
|
409
|
+
await EntityStorageIdentityConnector.verifyDocument(issuerIdentityDocument, this._vaultConnector);
|
|
420
410
|
const issuerDidDocument = issuerIdentityDocument.document;
|
|
421
411
|
const methods = this.getAllMethods(issuerDidDocument);
|
|
422
412
|
const methodAndArray = methods.find(m => {
|
|
@@ -426,32 +416,30 @@ class EntityStorageIdentityConnector {
|
|
|
426
416
|
return m.method.id === verificationMethodId;
|
|
427
417
|
});
|
|
428
418
|
if (!methodAndArray) {
|
|
429
|
-
throw new core.GeneralError(this.CLASS_NAME, "methodMissing");
|
|
419
|
+
throw new core.GeneralError(this.CLASS_NAME, "methodMissing", { method: verificationMethodId });
|
|
430
420
|
}
|
|
431
421
|
const verificationDidMethod = methodAndArray.method;
|
|
432
422
|
if (!core.Is.stringValue(verificationDidMethod.publicKeyJwk?.x)) {
|
|
433
|
-
throw new core.GeneralError(this.CLASS_NAME, "publicKeyJwkMissing"
|
|
423
|
+
throw new core.GeneralError(this.CLASS_NAME, "publicKeyJwkMissing", {
|
|
424
|
+
method: verificationMethodId
|
|
425
|
+
});
|
|
434
426
|
}
|
|
435
427
|
const revocationService = issuerDidDocument.service?.find(s => s.id.endsWith("#revocation"));
|
|
436
|
-
const
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
finalContexts.push(...contexts);
|
|
446
|
-
}
|
|
447
|
-
else if (core.Is.stringValue(contexts)) {
|
|
448
|
-
finalContexts.push(contexts);
|
|
428
|
+
const subjectClone = core.ObjectHelper.clone(subject);
|
|
429
|
+
const finalTypes = [standardsW3cDid.DidTypes.VerifiableCredential];
|
|
430
|
+
const credContext = core.ObjectHelper.extractProperty(subjectClone, [
|
|
431
|
+
"@context"
|
|
432
|
+
]);
|
|
433
|
+
const credId = core.ObjectHelper.extractProperty(subjectClone, ["@id", "id"], false);
|
|
434
|
+
const credType = core.ObjectHelper.extractProperty(subjectClone, ["@type", "type"]);
|
|
435
|
+
if (core.Is.stringValue(credType)) {
|
|
436
|
+
finalTypes.push(credType);
|
|
449
437
|
}
|
|
450
438
|
const verifiableCredential = {
|
|
451
|
-
"@context":
|
|
452
|
-
id
|
|
439
|
+
"@context": dataJsonLd.JsonLdProcessor.combineContexts(standardsW3cDid.DidContexts.ContextVCv2, credContext),
|
|
440
|
+
id,
|
|
453
441
|
type: finalTypes,
|
|
454
|
-
credentialSubject:
|
|
442
|
+
credentialSubject: subjectClone,
|
|
455
443
|
issuer: issuerDidDocument.id,
|
|
456
444
|
issuanceDate: new Date().toISOString(),
|
|
457
445
|
credentialStatus: revocationService && !core.Is.undefined(revocationIndex)
|
|
@@ -488,15 +476,10 @@ class EntityStorageIdentityConnector {
|
|
|
488
476
|
iss: idParts.id,
|
|
489
477
|
nbf: Math.floor(Date.now() / 1000),
|
|
490
478
|
jti: verifiableCredential.id,
|
|
491
|
-
sub:
|
|
492
|
-
? core.ObjectHelper.propertyGet(subject[0], "id")
|
|
493
|
-
: core.ObjectHelper.propertyGet(subject, "id"),
|
|
479
|
+
sub: credId,
|
|
494
480
|
vc: jwtVc
|
|
495
481
|
};
|
|
496
|
-
const signature = await web.Jwt.encodeWithSigner(jwtHeader, jwtPayload, async (
|
|
497
|
-
const sig = await this._vaultConnector.sign(this.buildVaultKey(idParts.id, verificationMethodId), payload);
|
|
498
|
-
return sig;
|
|
499
|
-
});
|
|
482
|
+
const signature = await web.Jwt.encodeWithSigner(jwtHeader, jwtPayload, async (header, payload) => vaultModels.VaultConnectorHelper.jwtSigner(this._vaultConnector, EntityStorageIdentityConnector.buildVaultKey(idParts.id, idParts.fragment ?? ""), header, payload));
|
|
500
483
|
return {
|
|
501
484
|
verifiableCredential,
|
|
502
485
|
jwt: signature
|
|
@@ -529,7 +512,7 @@ class EntityStorageIdentityConnector {
|
|
|
529
512
|
if (core.Is.undefined(issuerIdentityDocument)) {
|
|
530
513
|
throw new core.NotFoundError(this.CLASS_NAME, "documentNotFound", issuerDocumentId);
|
|
531
514
|
}
|
|
532
|
-
await
|
|
515
|
+
await EntityStorageIdentityConnector.verifyDocument(issuerIdentityDocument, this._vaultConnector);
|
|
533
516
|
const issuerDidDocument = issuerIdentityDocument.document;
|
|
534
517
|
const methods = this.getAllMethods(issuerDidDocument);
|
|
535
518
|
const methodAndArray = methods.find(m => {
|
|
@@ -539,16 +522,13 @@ class EntityStorageIdentityConnector {
|
|
|
539
522
|
return m.method.id === jwtHeader.kid;
|
|
540
523
|
});
|
|
541
524
|
if (!methodAndArray) {
|
|
542
|
-
throw new core.GeneralError(this.CLASS_NAME, "methodMissing");
|
|
525
|
+
throw new core.GeneralError(this.CLASS_NAME, "methodMissing", { method: jwtHeader.kid });
|
|
543
526
|
}
|
|
544
527
|
const didMethod = methodAndArray.method;
|
|
545
528
|
if (!core.Is.stringValue(didMethod.publicKeyJwk?.x)) {
|
|
546
|
-
throw new core.GeneralError(this.CLASS_NAME, "publicKeyJwkMissing");
|
|
547
|
-
}
|
|
548
|
-
const verified = web.Jwt.verifySignature(jwtHeader, jwtPayload, jwtSignature, core.Converter.base64UrlToBytes(didMethod.publicKeyJwk.x));
|
|
549
|
-
if (!verified) {
|
|
550
|
-
throw new core.GeneralError(this.CLASS_NAME, "jwkSignatureFailed");
|
|
529
|
+
throw new core.GeneralError(this.CLASS_NAME, "publicKeyJwkMissing", { method: jwtHeader.kid });
|
|
551
530
|
}
|
|
531
|
+
await web.Jwt.verifySignature(credentialJwt, await web.Jwk.toCryptoKey(didMethod.publicKeyJwk));
|
|
552
532
|
const verifiableCredential = jwtPayload.vc;
|
|
553
533
|
if (core.Is.object(verifiableCredential)) {
|
|
554
534
|
if (core.Is.string(jwtPayload.jti)) {
|
|
@@ -568,7 +548,19 @@ class EntityStorageIdentityConnector {
|
|
|
568
548
|
core.ObjectHelper.propertySet(verifiableCredential.credentialSubject, "id", jwtPayload.sub);
|
|
569
549
|
}
|
|
570
550
|
}
|
|
571
|
-
const
|
|
551
|
+
const credentialStatus = verifiableCredential.credentialStatus;
|
|
552
|
+
let revoked = false;
|
|
553
|
+
if (core.Is.object(credentialStatus)) {
|
|
554
|
+
revoked = await this.checkRevocation(issuerDidDocument, credentialStatus.revocationBitmapIndex);
|
|
555
|
+
}
|
|
556
|
+
else if (core.Is.arrayValue(credentialStatus)) {
|
|
557
|
+
for (let i = 0; i < credentialStatus.length; i++) {
|
|
558
|
+
revoked = await this.checkRevocation(issuerDidDocument, credentialStatus[i].revocationBitmapIndex);
|
|
559
|
+
if (revoked) {
|
|
560
|
+
break;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
572
564
|
return {
|
|
573
565
|
revoked,
|
|
574
566
|
verifiableCredential: revoked ? undefined : verifiableCredential
|
|
@@ -594,7 +586,7 @@ class EntityStorageIdentityConnector {
|
|
|
594
586
|
if (core.Is.undefined(issuerIdentityDocument)) {
|
|
595
587
|
throw new core.NotFoundError(this.CLASS_NAME, "documentNotFound", issuerDocumentId);
|
|
596
588
|
}
|
|
597
|
-
await
|
|
589
|
+
await EntityStorageIdentityConnector.verifyDocument(issuerIdentityDocument, this._vaultConnector);
|
|
598
590
|
const issuerDidDocument = issuerIdentityDocument.document;
|
|
599
591
|
const revocationService = issuerDidDocument.service?.find(s => s.id.endsWith("#revocation"));
|
|
600
592
|
if (revocationService &&
|
|
@@ -634,7 +626,7 @@ class EntityStorageIdentityConnector {
|
|
|
634
626
|
if (core.Is.undefined(issuerIdentityDocument)) {
|
|
635
627
|
throw new core.NotFoundError(this.CLASS_NAME, "documentNotFound", issuerDocumentId);
|
|
636
628
|
}
|
|
637
|
-
await
|
|
629
|
+
await EntityStorageIdentityConnector.verifyDocument(issuerIdentityDocument, this._vaultConnector);
|
|
638
630
|
const issuerDidDocument = issuerIdentityDocument.document;
|
|
639
631
|
const revocationService = issuerDidDocument.service?.find(s => s.id.endsWith("#revocation"));
|
|
640
632
|
if (revocationService &&
|
|
@@ -661,17 +653,18 @@ class EntityStorageIdentityConnector {
|
|
|
661
653
|
/**
|
|
662
654
|
* Create a verifiable presentation from the supplied verifiable credentials.
|
|
663
655
|
* @param controller The controller of the identity who can make changes.
|
|
664
|
-
* @param
|
|
656
|
+
* @param verificationMethodId The method to associate with the presentation.
|
|
657
|
+
* @param presentationId The id of the presentation.
|
|
658
|
+
* @param contexts The contexts for the data stored in the verifiable credential.
|
|
665
659
|
* @param types The types for the data stored in the verifiable credential.
|
|
666
660
|
* @param verifiableCredentials The credentials to use for creating the presentation in jwt format.
|
|
667
|
-
* @param contexts Additional contexts to include in the presentation.
|
|
668
661
|
* @param expiresInMinutes The time in minutes for the presentation to expire.
|
|
669
662
|
* @returns The created verifiable presentation and its token.
|
|
670
663
|
* @throws NotFoundError if the id can not be resolved.
|
|
671
664
|
*/
|
|
672
|
-
async createVerifiablePresentation(controller,
|
|
665
|
+
async createVerifiablePresentation(controller, verificationMethodId, presentationId, contexts, types, verifiableCredentials, expiresInMinutes) {
|
|
673
666
|
core.Guards.stringValue(this.CLASS_NAME, "controller", controller);
|
|
674
|
-
core.Guards.stringValue(this.CLASS_NAME, "
|
|
667
|
+
core.Guards.stringValue(this.CLASS_NAME, "verificationMethodId", verificationMethodId);
|
|
675
668
|
if (core.Is.array(types)) {
|
|
676
669
|
core.Guards.arrayValue(this.CLASS_NAME, "types", types);
|
|
677
670
|
}
|
|
@@ -679,56 +672,46 @@ class EntityStorageIdentityConnector {
|
|
|
679
672
|
core.Guards.stringValue(this.CLASS_NAME, "types", types);
|
|
680
673
|
}
|
|
681
674
|
core.Guards.arrayValue(this.CLASS_NAME, "verifiableCredentials", verifiableCredentials);
|
|
682
|
-
if (core.Is.array(contexts)) {
|
|
683
|
-
core.Guards.arrayValue(this.CLASS_NAME, "contexts", contexts);
|
|
684
|
-
}
|
|
685
|
-
else if (core.Is.string(contexts)) {
|
|
686
|
-
core.Guards.stringValue(this.CLASS_NAME, "contexts", contexts);
|
|
687
|
-
}
|
|
688
675
|
if (!core.Is.undefined(expiresInMinutes)) {
|
|
689
676
|
core.Guards.integer(this.CLASS_NAME, "expiresInMinutes", expiresInMinutes);
|
|
690
677
|
}
|
|
691
678
|
try {
|
|
692
|
-
const idParts = identityModels.DocumentHelper.
|
|
693
|
-
if (core.Is.empty(idParts.
|
|
694
|
-
throw new core.NotFoundError(this.CLASS_NAME, "missingDid",
|
|
679
|
+
const idParts = identityModels.DocumentHelper.parseId(verificationMethodId);
|
|
680
|
+
if (core.Is.empty(idParts.fragment)) {
|
|
681
|
+
throw new core.NotFoundError(this.CLASS_NAME, "missingDid", verificationMethodId);
|
|
695
682
|
}
|
|
696
683
|
const holderIdentityDocument = await this._didDocumentEntityStorage.get(idParts.id);
|
|
697
684
|
if (core.Is.undefined(holderIdentityDocument)) {
|
|
698
685
|
throw new core.NotFoundError(this.CLASS_NAME, "documentNotFound", idParts.id);
|
|
699
686
|
}
|
|
700
|
-
await
|
|
687
|
+
await EntityStorageIdentityConnector.verifyDocument(holderIdentityDocument, this._vaultConnector);
|
|
701
688
|
const holderDidDocument = holderIdentityDocument.document;
|
|
702
689
|
const methods = this.getAllMethods(holderDidDocument);
|
|
703
690
|
const methodAndArray = methods.find(m => {
|
|
704
691
|
if (core.Is.string(m.method)) {
|
|
705
|
-
return m.method ===
|
|
692
|
+
return m.method === verificationMethodId;
|
|
706
693
|
}
|
|
707
|
-
return m.method.id ===
|
|
694
|
+
return m.method.id === verificationMethodId;
|
|
708
695
|
});
|
|
709
696
|
if (!methodAndArray) {
|
|
710
|
-
throw new core.GeneralError(this.CLASS_NAME, "methodMissing");
|
|
697
|
+
throw new core.GeneralError(this.CLASS_NAME, "methodMissing", { method: verificationMethodId });
|
|
711
698
|
}
|
|
712
699
|
const didMethod = methodAndArray.method;
|
|
713
700
|
if (!core.Is.stringValue(didMethod.publicKeyJwk?.x)) {
|
|
714
|
-
throw new core.GeneralError(this.CLASS_NAME, "publicKeyJwkMissing"
|
|
701
|
+
throw new core.GeneralError(this.CLASS_NAME, "publicKeyJwkMissing", {
|
|
702
|
+
method: verificationMethodId
|
|
703
|
+
});
|
|
715
704
|
}
|
|
716
|
-
const finalTypes = [
|
|
705
|
+
const finalTypes = [standardsW3cDid.DidTypes.VerifiablePresentation];
|
|
717
706
|
if (core.Is.array(types)) {
|
|
718
707
|
finalTypes.push(...types);
|
|
719
708
|
}
|
|
720
709
|
else if (core.Is.stringValue(types)) {
|
|
721
710
|
finalTypes.push(types);
|
|
722
711
|
}
|
|
723
|
-
const finalContexts = ["https://www.w3.org/2018/credentials/v1"];
|
|
724
|
-
if (core.Is.array(contexts)) {
|
|
725
|
-
finalContexts.push(...contexts);
|
|
726
|
-
}
|
|
727
|
-
else if (core.Is.stringValue(contexts)) {
|
|
728
|
-
finalContexts.push(contexts);
|
|
729
|
-
}
|
|
730
712
|
const verifiablePresentation = {
|
|
731
|
-
"@context":
|
|
713
|
+
"@context": dataJsonLd.JsonLdProcessor.combineContexts(standardsW3cDid.DidContexts.ContextVCv2, contexts),
|
|
714
|
+
id: presentationId,
|
|
732
715
|
type: finalTypes,
|
|
733
716
|
verifiableCredential: verifiableCredentials,
|
|
734
717
|
holder: idParts.id
|
|
@@ -752,10 +735,7 @@ class EntityStorageIdentityConnector {
|
|
|
752
735
|
const expiresInSeconds = expiresInMinutes * 60;
|
|
753
736
|
jwtPayload.exp = Math.floor(Date.now() / 1000) + expiresInSeconds;
|
|
754
737
|
}
|
|
755
|
-
const signature = await web.Jwt.encodeWithSigner(jwtHeader, jwtPayload, async (
|
|
756
|
-
const sig = await this._vaultConnector.sign(this.buildVaultKey(idParts.id, presentationMethodId), payload);
|
|
757
|
-
return sig;
|
|
758
|
-
});
|
|
738
|
+
const signature = await web.Jwt.encodeWithSigner(jwtHeader, jwtPayload, async (header, payload) => vaultModels.VaultConnectorHelper.jwtSigner(this._vaultConnector, EntityStorageIdentityConnector.buildVaultKey(idParts.id, idParts.fragment ?? ""), header, payload));
|
|
759
739
|
return {
|
|
760
740
|
verifiablePresentation,
|
|
761
741
|
jwt: signature
|
|
@@ -788,29 +768,54 @@ class EntityStorageIdentityConnector {
|
|
|
788
768
|
if (core.Is.undefined(holderIdentityDocument)) {
|
|
789
769
|
throw new core.NotFoundError(this.CLASS_NAME, "documentNotFound", holderDocumentId);
|
|
790
770
|
}
|
|
791
|
-
await
|
|
771
|
+
await EntityStorageIdentityConnector.verifyDocument(holderIdentityDocument, this._vaultConnector);
|
|
792
772
|
const issuers = [];
|
|
793
773
|
const tokensRevoked = [];
|
|
794
774
|
const verifiablePresentation = jwtPayload?.vp;
|
|
795
775
|
if (core.Is.object(verifiablePresentation) &&
|
|
796
776
|
core.Is.array(verifiablePresentation.verifiableCredential)) {
|
|
797
777
|
for (const vcJwt of verifiablePresentation.verifiableCredential) {
|
|
798
|
-
const jwt = await web.Jwt.decode(vcJwt);
|
|
799
778
|
let revoked = true;
|
|
800
|
-
if (core.Is.
|
|
801
|
-
const
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
779
|
+
if (core.Is.stringValue(vcJwt)) {
|
|
780
|
+
const jwt = await web.Jwt.decode(vcJwt);
|
|
781
|
+
if (core.Is.string(jwt.payload?.iss)) {
|
|
782
|
+
const issuerDocumentId = jwt.payload.iss;
|
|
783
|
+
verifiablePresentation.holder = issuerDocumentId;
|
|
784
|
+
const issuerDidDocument = await this._didDocumentEntityStorage.get(issuerDocumentId);
|
|
785
|
+
if (core.Is.undefined(issuerDidDocument)) {
|
|
786
|
+
throw new core.NotFoundError(this.CLASS_NAME, "documentNotFound", issuerDocumentId);
|
|
787
|
+
}
|
|
788
|
+
await EntityStorageIdentityConnector.verifyDocument(issuerDidDocument, this._vaultConnector);
|
|
789
|
+
issuers.push({
|
|
790
|
+
"@context": standardsW3cDid.DidContexts.Context,
|
|
791
|
+
...issuerDidDocument
|
|
792
|
+
});
|
|
793
|
+
const vc = jwt.payload.vc;
|
|
794
|
+
if (core.Is.object(vc)) {
|
|
795
|
+
const credentialStatus = vc.credentialStatus;
|
|
796
|
+
if (core.Is.object(credentialStatus)) {
|
|
797
|
+
revoked = await this.checkRevocation({
|
|
798
|
+
"@context": standardsW3cDid.DidContexts.Context,
|
|
799
|
+
...issuerDidDocument
|
|
800
|
+
}, credentialStatus.revocationBitmapIndex);
|
|
801
|
+
}
|
|
802
|
+
else if (core.Is.arrayValue(credentialStatus)) {
|
|
803
|
+
for (let i = 0; i < credentialStatus.length; i++) {
|
|
804
|
+
revoked = await this.checkRevocation({
|
|
805
|
+
"@context": standardsW3cDid.DidContexts.Context,
|
|
806
|
+
...issuerDidDocument
|
|
807
|
+
}, credentialStatus[i].revocationBitmapIndex);
|
|
808
|
+
if (revoked) {
|
|
809
|
+
break;
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
}
|
|
812
814
|
}
|
|
813
815
|
}
|
|
816
|
+
else {
|
|
817
|
+
revoked = false;
|
|
818
|
+
}
|
|
814
819
|
tokensRevoked.push(revoked);
|
|
815
820
|
}
|
|
816
821
|
}
|
|
@@ -833,23 +838,25 @@ class EntityStorageIdentityConnector {
|
|
|
833
838
|
* Create a proof for arbitrary data with the specified verification method.
|
|
834
839
|
* @param controller The controller of the identity who can make changes.
|
|
835
840
|
* @param verificationMethodId The verification method id to use.
|
|
836
|
-
* @param
|
|
837
|
-
* @
|
|
841
|
+
* @param proofType The type of proof to create.
|
|
842
|
+
* @param unsecureDocument The unsecure document to create the proof for.
|
|
843
|
+
* @returns The proof.
|
|
838
844
|
*/
|
|
839
|
-
async createProof(controller, verificationMethodId,
|
|
845
|
+
async createProof(controller, verificationMethodId, proofType, unsecureDocument) {
|
|
840
846
|
core.Guards.stringValue(this.CLASS_NAME, "controller", controller);
|
|
841
847
|
core.Guards.stringValue(this.CLASS_NAME, "verificationMethodId", verificationMethodId);
|
|
842
|
-
core.Guards.
|
|
848
|
+
core.Guards.arrayOneOf(this.CLASS_NAME, "proofType", proofType, Object.values(standardsW3cDid.ProofTypes));
|
|
849
|
+
core.Guards.object(this.CLASS_NAME, "unsecureDocument", unsecureDocument);
|
|
843
850
|
try {
|
|
844
|
-
const idParts = identityModels.DocumentHelper.
|
|
845
|
-
if (core.Is.empty(idParts.
|
|
851
|
+
const idParts = identityModels.DocumentHelper.parseId(verificationMethodId);
|
|
852
|
+
if (core.Is.empty(idParts.fragment)) {
|
|
846
853
|
throw new core.NotFoundError(this.CLASS_NAME, "missingDid", verificationMethodId);
|
|
847
854
|
}
|
|
848
855
|
const didIdentityDocument = await this._didDocumentEntityStorage.get(idParts.id);
|
|
849
856
|
if (core.Is.undefined(didIdentityDocument)) {
|
|
850
857
|
throw new core.NotFoundError(this.CLASS_NAME, "documentNotFound", idParts.id);
|
|
851
858
|
}
|
|
852
|
-
await
|
|
859
|
+
await EntityStorageIdentityConnector.verifyDocument(didIdentityDocument, this._vaultConnector);
|
|
853
860
|
const didDocument = didIdentityDocument.document;
|
|
854
861
|
const methods = this.getAllMethods(didDocument);
|
|
855
862
|
const methodAndArray = methods.find(m => {
|
|
@@ -859,17 +866,18 @@ class EntityStorageIdentityConnector {
|
|
|
859
866
|
return m.method.id === verificationMethodId;
|
|
860
867
|
});
|
|
861
868
|
if (!methodAndArray) {
|
|
862
|
-
throw new core.GeneralError(this.CLASS_NAME, "methodMissing");
|
|
869
|
+
throw new core.GeneralError(this.CLASS_NAME, "methodMissing", { method: verificationMethodId });
|
|
863
870
|
}
|
|
864
871
|
const didMethod = methodAndArray.method;
|
|
865
872
|
if (!core.Is.stringValue(didMethod.publicKeyJwk?.x)) {
|
|
866
|
-
throw new core.GeneralError(this.CLASS_NAME, "publicKeyJwkMissing"
|
|
873
|
+
throw new core.GeneralError(this.CLASS_NAME, "publicKeyJwkMissing", {
|
|
874
|
+
method: verificationMethodId
|
|
875
|
+
});
|
|
867
876
|
}
|
|
868
|
-
const
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
};
|
|
877
|
+
const vaultKey = EntityStorageIdentityConnector.buildVaultKey(didDocument.id, idParts.fragment ?? "");
|
|
878
|
+
const key = await this._vaultConnector.getKey(vaultKey);
|
|
879
|
+
const signedProof = await standardsW3cDid.ProofHelper.createProof(proofType, unsecureDocument, standardsW3cDid.ProofHelper.createUnsignedProof(proofType, verificationMethodId), await web.Jwk.fromEd25519Private(key.privateKey));
|
|
880
|
+
return signedProof;
|
|
873
881
|
}
|
|
874
882
|
catch (error) {
|
|
875
883
|
throw new core.GeneralError(this.CLASS_NAME, "createProofFailed", undefined, error);
|
|
@@ -877,43 +885,44 @@ class EntityStorageIdentityConnector {
|
|
|
877
885
|
}
|
|
878
886
|
/**
|
|
879
887
|
* Verify proof for arbitrary data with the specified verification method.
|
|
880
|
-
* @param
|
|
881
|
-
* @param
|
|
882
|
-
* @
|
|
883
|
-
* @param signatureValue The value of the signature for the proof.
|
|
884
|
-
* @returns True if the signature is valid.
|
|
888
|
+
* @param document The document to verify.
|
|
889
|
+
* @param proof The proof to verify.
|
|
890
|
+
* @returns True if the proof is verified.
|
|
885
891
|
*/
|
|
886
|
-
async verifyProof(
|
|
887
|
-
core.Guards.
|
|
888
|
-
core.Guards.
|
|
889
|
-
core.Guards.stringValue(this.CLASS_NAME, "
|
|
890
|
-
core.Guards.uint8Array(this.CLASS_NAME, "signatureValue", signatureValue);
|
|
892
|
+
async verifyProof(document, proof) {
|
|
893
|
+
core.Guards.object(this.CLASS_NAME, "document", document);
|
|
894
|
+
core.Guards.object(this.CLASS_NAME, "proof", proof);
|
|
895
|
+
core.Guards.stringValue(this.CLASS_NAME, "proof.verificationMethod", proof.verificationMethod);
|
|
891
896
|
try {
|
|
892
|
-
const idParts = identityModels.DocumentHelper.
|
|
893
|
-
if (core.Is.empty(idParts.
|
|
894
|
-
throw new core.NotFoundError(this.CLASS_NAME, "missingDid",
|
|
897
|
+
const idParts = identityModels.DocumentHelper.parseId(proof.verificationMethod);
|
|
898
|
+
if (core.Is.empty(idParts.fragment)) {
|
|
899
|
+
throw new core.NotFoundError(this.CLASS_NAME, "missingDid", proof.verificationMethod);
|
|
895
900
|
}
|
|
896
901
|
const didIdentityDocument = await this._didDocumentEntityStorage.get(idParts.id);
|
|
897
902
|
if (core.Is.undefined(didIdentityDocument)) {
|
|
898
903
|
throw new core.NotFoundError(this.CLASS_NAME, "documentNotFound", idParts.id);
|
|
899
904
|
}
|
|
900
|
-
await
|
|
905
|
+
await EntityStorageIdentityConnector.verifyDocument(didIdentityDocument, this._vaultConnector);
|
|
901
906
|
const didDocument = didIdentityDocument.document;
|
|
902
907
|
const methods = this.getAllMethods(didDocument);
|
|
903
908
|
const methodAndArray = methods.find(m => {
|
|
904
909
|
if (core.Is.string(m.method)) {
|
|
905
|
-
return m.method ===
|
|
910
|
+
return m.method === proof.verificationMethod;
|
|
906
911
|
}
|
|
907
|
-
return m.method.id ===
|
|
912
|
+
return m.method.id === proof.verificationMethod;
|
|
908
913
|
});
|
|
909
914
|
if (!methodAndArray) {
|
|
910
|
-
throw new core.GeneralError(this.CLASS_NAME, "methodMissing"
|
|
915
|
+
throw new core.GeneralError(this.CLASS_NAME, "methodMissing", {
|
|
916
|
+
method: proof.verificationMethod
|
|
917
|
+
});
|
|
911
918
|
}
|
|
912
919
|
const didMethod = methodAndArray.method;
|
|
913
920
|
if (!core.Is.stringValue(didMethod.publicKeyJwk?.x)) {
|
|
914
|
-
throw new core.GeneralError(this.CLASS_NAME, "publicKeyJwkMissing"
|
|
921
|
+
throw new core.GeneralError(this.CLASS_NAME, "publicKeyJwkMissing", {
|
|
922
|
+
method: proof.verificationMethod
|
|
923
|
+
});
|
|
915
924
|
}
|
|
916
|
-
return
|
|
925
|
+
return standardsW3cDid.ProofHelper.verifyProof(document, proof, didMethod.publicKeyJwk);
|
|
917
926
|
}
|
|
918
927
|
catch (error) {
|
|
919
928
|
throw new core.GeneralError(this.CLASS_NAME, "verifyProofFailed", undefined, error);
|
|
@@ -966,19 +975,6 @@ class EntityStorageIdentityConnector {
|
|
|
966
975
|
}
|
|
967
976
|
return false;
|
|
968
977
|
}
|
|
969
|
-
/**
|
|
970
|
-
* Verify the document in storage.
|
|
971
|
-
* @param didDocument The did document that was stored.
|
|
972
|
-
* @internal
|
|
973
|
-
*/
|
|
974
|
-
async verifyDocument(didDocument) {
|
|
975
|
-
const stringifiedDocument = core.JsonHelper.canonicalize(didDocument.document);
|
|
976
|
-
const docBytes = core.Converter.utf8ToBytes(stringifiedDocument);
|
|
977
|
-
const verified = await this._vaultConnector.verify(this.buildVaultKey(didDocument.id, didDocument.id), docBytes, core.Converter.base64ToBytes(didDocument.signature));
|
|
978
|
-
if (!verified) {
|
|
979
|
-
throw new core.GeneralError(this.CLASS_NAME, "signatureVerificationFailed");
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
978
|
/**
|
|
983
979
|
* Update the document in storage.
|
|
984
980
|
* @param controller The controller of the document.
|
|
@@ -988,7 +984,7 @@ class EntityStorageIdentityConnector {
|
|
|
988
984
|
async updateDocument(controller, didDocument) {
|
|
989
985
|
const stringifiedDocument = core.JsonHelper.canonicalize(didDocument);
|
|
990
986
|
const docBytes = core.Converter.utf8ToBytes(stringifiedDocument);
|
|
991
|
-
const signature = await this._vaultConnector.sign(
|
|
987
|
+
const signature = await this._vaultConnector.sign(EntityStorageIdentityConnector.buildVaultKey(didDocument.id, "did"), docBytes);
|
|
992
988
|
await this._didDocumentEntityStorage.set({
|
|
993
989
|
id: didDocument.id,
|
|
994
990
|
document: didDocument,
|
|
@@ -996,15 +992,6 @@ class EntityStorageIdentityConnector {
|
|
|
996
992
|
controller
|
|
997
993
|
});
|
|
998
994
|
}
|
|
999
|
-
/**
|
|
1000
|
-
* Build the key name to access the specified key in the vault.
|
|
1001
|
-
* @param identity The identity of the user to access the vault keys.
|
|
1002
|
-
* @returns The vault key.
|
|
1003
|
-
* @internal
|
|
1004
|
-
*/
|
|
1005
|
-
buildVaultKey(identity, key) {
|
|
1006
|
-
return `${identity}/${key}`;
|
|
1007
|
-
}
|
|
1008
995
|
}
|
|
1009
996
|
|
|
1010
997
|
// Copyright 2024 IOTA Stiftung.
|
|
@@ -1027,9 +1014,8 @@ class EntityStorageIdentityProfileConnector {
|
|
|
1027
1014
|
*/
|
|
1028
1015
|
_profileEntityStorage;
|
|
1029
1016
|
/**
|
|
1030
|
-
* Create a new instance of
|
|
1031
|
-
* @param options The
|
|
1032
|
-
* @param options.profileEntityStorageType The storage connector for the profiles, default to "identity-profile".
|
|
1017
|
+
* Create a new instance of EntityStorageIdentityProfileConnector.
|
|
1018
|
+
* @param options The options for the identity service.
|
|
1033
1019
|
*/
|
|
1034
1020
|
constructor(options) {
|
|
1035
1021
|
this._profileEntityStorage = entityStorageModels.EntityStorageConnectorFactory.get(options?.profileEntityStorageType ?? "identity-profile");
|
|
@@ -1201,6 +1187,60 @@ class EntityStorageIdentityProfileConnector {
|
|
|
1201
1187
|
}
|
|
1202
1188
|
}
|
|
1203
1189
|
|
|
1190
|
+
// Copyright 2024 IOTA Stiftung.
|
|
1191
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
1192
|
+
/**
|
|
1193
|
+
* Class for performing identity operations using entity storage.
|
|
1194
|
+
*/
|
|
1195
|
+
class EntityStorageIdentityResolverConnector {
|
|
1196
|
+
/**
|
|
1197
|
+
* The namespace supported by the identity connector.
|
|
1198
|
+
*/
|
|
1199
|
+
static NAMESPACE = "entity-storage";
|
|
1200
|
+
/**
|
|
1201
|
+
* Runtime name for the class.
|
|
1202
|
+
*/
|
|
1203
|
+
CLASS_NAME = "EntityStorageIdentityResolverConnector";
|
|
1204
|
+
/**
|
|
1205
|
+
* The entity storage for identities.
|
|
1206
|
+
* @internal
|
|
1207
|
+
*/
|
|
1208
|
+
_didDocumentEntityStorage;
|
|
1209
|
+
/**
|
|
1210
|
+
* The vault for the keys.
|
|
1211
|
+
* @internal
|
|
1212
|
+
*/
|
|
1213
|
+
_vaultConnector;
|
|
1214
|
+
/**
|
|
1215
|
+
* Create a new instance of EntityStorageIdentityResolverConnector.
|
|
1216
|
+
* @param options The options for the identity connector.
|
|
1217
|
+
*/
|
|
1218
|
+
constructor(options) {
|
|
1219
|
+
this._didDocumentEntityStorage = entityStorageModels.EntityStorageConnectorFactory.get(options?.didDocumentEntityStorageType ?? "identity-document");
|
|
1220
|
+
this._vaultConnector = vaultModels.VaultConnectorFactory.get(options?.vaultConnectorType ?? "vault");
|
|
1221
|
+
}
|
|
1222
|
+
/**
|
|
1223
|
+
* Resolve a document from its id.
|
|
1224
|
+
* @param documentId The id of the document to resolve.
|
|
1225
|
+
* @returns The resolved document.
|
|
1226
|
+
* @throws NotFoundError if the id can not be resolved.
|
|
1227
|
+
*/
|
|
1228
|
+
async resolveDocument(documentId) {
|
|
1229
|
+
core.Guards.stringValue(this.CLASS_NAME, "documentId", documentId);
|
|
1230
|
+
try {
|
|
1231
|
+
const didIdentityDocument = await this._didDocumentEntityStorage.get(documentId);
|
|
1232
|
+
if (core.Is.undefined(didIdentityDocument)) {
|
|
1233
|
+
throw new core.NotFoundError(this.CLASS_NAME, "documentNotFound", documentId);
|
|
1234
|
+
}
|
|
1235
|
+
await EntityStorageIdentityConnector.verifyDocument(didIdentityDocument, this._vaultConnector);
|
|
1236
|
+
return didIdentityDocument.document;
|
|
1237
|
+
}
|
|
1238
|
+
catch (error) {
|
|
1239
|
+
throw new core.GeneralError(this.CLASS_NAME, "resolveDocumentFailed", undefined, error);
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1204
1244
|
// Copyright 2024 IOTA Stiftung.
|
|
1205
1245
|
// SPDX-License-Identifier: Apache-2.0.
|
|
1206
1246
|
/**
|
|
@@ -1220,4 +1260,5 @@ function initSchema(options) {
|
|
|
1220
1260
|
|
|
1221
1261
|
exports.EntityStorageIdentityConnector = EntityStorageIdentityConnector;
|
|
1222
1262
|
exports.EntityStorageIdentityProfileConnector = EntityStorageIdentityProfileConnector;
|
|
1263
|
+
exports.EntityStorageIdentityResolverConnector = EntityStorageIdentityResolverConnector;
|
|
1223
1264
|
exports.initSchema = initSchema;
|