@twin.org/identity-connector-entity-storage 0.0.3-next.2 → 0.0.3-next.20
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/README.md +2 -2
- package/dist/es/entityStorageIdentityConnector.js +171 -27
- package/dist/es/entityStorageIdentityConnector.js.map +1 -1
- package/dist/es/entityStorageIdentityProfileConnector.js.map +1 -1
- package/dist/es/models/IEntityStorageIdentityConnectorConstructorOptions.js.map +1 -1
- package/dist/types/entityStorageIdentityConnector.d.ts +37 -8
- package/docs/changelog.md +366 -69
- package/docs/examples.md +221 -1
- package/docs/reference/classes/EntityStorageIdentityConnector.md +148 -40
- package/docs/reference/classes/EntityStorageIdentityProfileConnector.md +8 -8
- package/docs/reference/classes/EntityStorageIdentityResolverConnector.md +4 -4
- package/docs/reference/classes/IdentityDocument.md +4 -4
- package/docs/reference/classes/IdentityProfile.md +5 -5
- package/docs/reference/interfaces/IEntityStorageIdentityConnectorConstructorOptions.md +4 -4
- package/docs/reference/interfaces/IEntityStorageIdentityProfileConnectorConstructorOptions.md +2 -2
- package/docs/reference/interfaces/IEntityStorageIdentityResolverConnectorConstructorOptions.md +4 -4
- package/locales/en.json +21 -16
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# TWIN Identity
|
|
1
|
+
# TWIN Identity
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The identity-connector-entity-storage package provides an entity storage backed connector for identity workflows, enabling reliable persistence and retrieval of identity records. It supports implementations that need consistent storage semantics while staying aligned with shared contracts across the ecosystem.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// Copyright 2024 IOTA Stiftung.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
-
import { BaseError, BitString, Coerce, Compression, CompressionType, Converter, GeneralError, Guards, Is, JsonHelper, NotFoundError, ObjectHelper, RandomHelper } from "@twin.org/core";
|
|
4
|
-
import { JsonLdProcessor } from "@twin.org/data-json-ld";
|
|
3
|
+
import { ArrayHelper, BaseError, BitString, Coerce, Compression, CompressionType, Converter, GeneralError, Guards, Is, JsonHelper, NotFoundError, ObjectHelper, RandomHelper, Url, Urn } from "@twin.org/core";
|
|
4
|
+
import { JsonLdHelper, JsonLdProcessor } from "@twin.org/data-json-ld";
|
|
5
5
|
import { EntityStorageConnectorFactory } from "@twin.org/entity-storage-models";
|
|
6
6
|
import { DocumentHelper } from "@twin.org/identity-models";
|
|
7
|
-
import { DidContexts, DidTypes, DidVerificationMethodType, ProofHelper, ProofTypes } from "@twin.org/standards-w3c-did";
|
|
7
|
+
import { DidContexts, DidTypes, DidVerificationMethodType, JwsAlgorithms, ProofHelper, ProofTypes } from "@twin.org/standards-w3c-did";
|
|
8
8
|
import { VaultConnectorFactory, VaultConnectorHelper, VaultKeyType } from "@twin.org/vault-models";
|
|
9
9
|
import { Jwk, Jwt } from "@twin.org/web";
|
|
10
10
|
/**
|
|
@@ -147,9 +147,8 @@ export class EntityStorageIdentityConnector {
|
|
|
147
147
|
if (Is.stringValue(verificationMethodId)) {
|
|
148
148
|
// If there is a verification method id, we will try to get the key from the vault.
|
|
149
149
|
try {
|
|
150
|
-
const defaultMethodId = `${controller}/${verificationMethodId}`;
|
|
151
150
|
// If there is an existing key, we will use it.
|
|
152
|
-
const existingKey = await this._vaultConnector.getKey(
|
|
151
|
+
const existingKey = await this._vaultConnector.getKey(EntityStorageIdentityConnector.buildVaultKey(didDocument.id, verificationMethodId));
|
|
153
152
|
methodKeyPublic = existingKey.publicKey;
|
|
154
153
|
}
|
|
155
154
|
catch { }
|
|
@@ -352,6 +351,81 @@ export class EntityStorageIdentityConnector {
|
|
|
352
351
|
throw new GeneralError(EntityStorageIdentityConnector.CLASS_NAME, "removeServiceFailed", undefined, error);
|
|
353
352
|
}
|
|
354
353
|
}
|
|
354
|
+
/**
|
|
355
|
+
* Add an alias to the alsoKnownAs property on the document.
|
|
356
|
+
* If the alias is already present the operation is a no-op.
|
|
357
|
+
* @param controller The controller of the identity who can make changes.
|
|
358
|
+
* @param documentId The id of the document to update.
|
|
359
|
+
* @param alias The alias to add. Must be a Url or Urn (typically another DID).
|
|
360
|
+
* @returns Nothing.
|
|
361
|
+
* @throws GeneralError if the alias is not a Url or Urn.
|
|
362
|
+
* @throws NotFoundError if the id can not be resolved.
|
|
363
|
+
*/
|
|
364
|
+
async addAlsoKnownAs(controller, documentId, alias) {
|
|
365
|
+
Guards.stringValue(EntityStorageIdentityConnector.CLASS_NAME, "controller", controller);
|
|
366
|
+
Guards.stringValue(EntityStorageIdentityConnector.CLASS_NAME, "documentId", documentId);
|
|
367
|
+
Guards.stringValue(EntityStorageIdentityConnector.CLASS_NAME, "alias", alias);
|
|
368
|
+
if (!Url.tryParseExact(alias) && !Urn.tryParseExact(alias)) {
|
|
369
|
+
throw new GeneralError(EntityStorageIdentityConnector.CLASS_NAME, "invalidAlias", { alias });
|
|
370
|
+
}
|
|
371
|
+
try {
|
|
372
|
+
const didIdentityDocument = await this._didDocumentEntityStorage.get(documentId);
|
|
373
|
+
if (Is.undefined(didIdentityDocument)) {
|
|
374
|
+
throw new NotFoundError(EntityStorageIdentityConnector.CLASS_NAME, "documentNotFound", documentId);
|
|
375
|
+
}
|
|
376
|
+
await EntityStorageIdentityConnector.verifyDocument(didIdentityDocument, this._vaultConnector);
|
|
377
|
+
const didDocument = didIdentityDocument.document;
|
|
378
|
+
const existing = Is.array(didDocument.alsoKnownAs) ? didDocument.alsoKnownAs : [];
|
|
379
|
+
if (existing.includes(alias)) {
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
didDocument.alsoKnownAs = [...existing, alias];
|
|
383
|
+
await this.updateDocument(controller, didDocument);
|
|
384
|
+
}
|
|
385
|
+
catch (error) {
|
|
386
|
+
throw new GeneralError(EntityStorageIdentityConnector.CLASS_NAME, "addAlsoKnownAsFailed", undefined, error);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Remove an alias from the alsoKnownAs property on the document.
|
|
391
|
+
* If the alias is not present the operation is a no-op.
|
|
392
|
+
* @param controller The controller of the identity who can make changes.
|
|
393
|
+
* @param documentId The id of the document to update.
|
|
394
|
+
* @param alias The alias to remove. Must be a Url or Urn.
|
|
395
|
+
* @returns Nothing.
|
|
396
|
+
* @throws GeneralError if the alias is not a Url or Urn.
|
|
397
|
+
* @throws NotFoundError if the id can not be resolved.
|
|
398
|
+
*/
|
|
399
|
+
async removeAlsoKnownAs(controller, documentId, alias) {
|
|
400
|
+
Guards.stringValue(EntityStorageIdentityConnector.CLASS_NAME, "controller", controller);
|
|
401
|
+
Guards.stringValue(EntityStorageIdentityConnector.CLASS_NAME, "documentId", documentId);
|
|
402
|
+
Guards.stringValue(EntityStorageIdentityConnector.CLASS_NAME, "alias", alias);
|
|
403
|
+
if (!Url.tryParseExact(alias) && !Urn.tryParseExact(alias)) {
|
|
404
|
+
throw new GeneralError(EntityStorageIdentityConnector.CLASS_NAME, "invalidAlias", { alias });
|
|
405
|
+
}
|
|
406
|
+
try {
|
|
407
|
+
const didIdentityDocument = await this._didDocumentEntityStorage.get(documentId);
|
|
408
|
+
if (Is.undefined(didIdentityDocument)) {
|
|
409
|
+
throw new NotFoundError(EntityStorageIdentityConnector.CLASS_NAME, "documentNotFound", documentId);
|
|
410
|
+
}
|
|
411
|
+
await EntityStorageIdentityConnector.verifyDocument(didIdentityDocument, this._vaultConnector);
|
|
412
|
+
const didDocument = didIdentityDocument.document;
|
|
413
|
+
if (!Is.array(didDocument.alsoKnownAs) || !didDocument.alsoKnownAs.includes(alias)) {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
const filtered = didDocument.alsoKnownAs.filter(a => a !== alias);
|
|
417
|
+
if (filtered.length === 0) {
|
|
418
|
+
delete didDocument.alsoKnownAs;
|
|
419
|
+
}
|
|
420
|
+
else {
|
|
421
|
+
didDocument.alsoKnownAs = filtered;
|
|
422
|
+
}
|
|
423
|
+
await this.updateDocument(controller, didDocument);
|
|
424
|
+
}
|
|
425
|
+
catch (error) {
|
|
426
|
+
throw new GeneralError(EntityStorageIdentityConnector.CLASS_NAME, "removeAlsoKnownAsFailed", undefined, error);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
355
429
|
/**
|
|
356
430
|
* Create a verifiable credential for a verification method.
|
|
357
431
|
* @param controller The controller of the identity who can make changes.
|
|
@@ -371,6 +445,9 @@ export class EntityStorageIdentityConnector {
|
|
|
371
445
|
if (!Is.undefined(options?.revocationIndex)) {
|
|
372
446
|
Guards.number(EntityStorageIdentityConnector.CLASS_NAME, "options.revocationIndex", options.revocationIndex);
|
|
373
447
|
}
|
|
448
|
+
if (!Is.undefined(options?.expirationDate)) {
|
|
449
|
+
Guards.date(EntityStorageIdentityConnector.CLASS_NAME, "options.expirationDate", options.expirationDate);
|
|
450
|
+
}
|
|
374
451
|
try {
|
|
375
452
|
const idParts = DocumentHelper.parseId(verificationMethodId);
|
|
376
453
|
if (Is.empty(idParts.fragment)) {
|
|
@@ -412,7 +489,8 @@ export class EntityStorageIdentityConnector {
|
|
|
412
489
|
finalTypes.push(credType);
|
|
413
490
|
}
|
|
414
491
|
const verifiableCredential = {
|
|
415
|
-
"@context": JsonLdProcessor.combineContexts(DidContexts.ContextVCv1, credContext)
|
|
492
|
+
"@context": (JsonLdProcessor.combineContexts(DidContexts.ContextVCv1, credContext) ??
|
|
493
|
+
DidContexts.ContextVCv1),
|
|
416
494
|
id,
|
|
417
495
|
type: finalTypes,
|
|
418
496
|
credentialSubject: subjectClone,
|
|
@@ -434,7 +512,7 @@ export class EntityStorageIdentityConnector {
|
|
|
434
512
|
const jwtHeader = {
|
|
435
513
|
kid: verificationDidMethod.id,
|
|
436
514
|
typ: "JWT",
|
|
437
|
-
alg:
|
|
515
|
+
alg: JwsAlgorithms.EdDSA
|
|
438
516
|
};
|
|
439
517
|
const jwtVc = ObjectHelper.pick(ObjectHelper.clone(verifiableCredential), [
|
|
440
518
|
"@context",
|
|
@@ -442,6 +520,15 @@ export class EntityStorageIdentityConnector {
|
|
|
442
520
|
"credentialSubject",
|
|
443
521
|
"credentialStatus"
|
|
444
522
|
]);
|
|
523
|
+
// Add the proof to the VC after extracting the jwt data
|
|
524
|
+
// as the jwt does not include the proof
|
|
525
|
+
verifiableCredential.proof = await this.createProof(controller, verificationMethodId, ProofTypes.DataIntegrityProof, JsonLdHelper.toNodeObject(verifiableCredential));
|
|
526
|
+
// As we are adding the receipt to the data we update the JSON-LD context
|
|
527
|
+
const proofContext = verifiableCredential.proof["@context"];
|
|
528
|
+
if (!Is.empty(proofContext)) {
|
|
529
|
+
verifiableCredential["@context"] = (JsonLdProcessor.combineContexts(verifiableCredential["@context"], proofContext) ?? verifiableCredential["@context"]);
|
|
530
|
+
delete verifiableCredential.proof["@context"];
|
|
531
|
+
}
|
|
445
532
|
if (Is.array(jwtVc.credentialSubject)) {
|
|
446
533
|
jwtVc.credentialSubject = jwtVc.credentialSubject.map(c => {
|
|
447
534
|
ObjectHelper.propertyDelete(c, "id");
|
|
@@ -458,6 +545,9 @@ export class EntityStorageIdentityConnector {
|
|
|
458
545
|
sub: credId,
|
|
459
546
|
vc: jwtVc
|
|
460
547
|
};
|
|
548
|
+
if (Is.date(options?.expirationDate)) {
|
|
549
|
+
jwtPayload.exp = Math.floor(options.expirationDate.getTime() / 1000);
|
|
550
|
+
}
|
|
461
551
|
const signature = await Jwt.encodeWithSigner(jwtHeader, jwtPayload, async (header, payload) => VaultConnectorHelper.jwtSigner(this._vaultConnector, EntityStorageIdentityConnector.buildVaultKey(idParts.id, idParts.fragment ?? ""), header, payload));
|
|
462
552
|
return {
|
|
463
553
|
verifiableCredential,
|
|
@@ -470,13 +560,23 @@ export class EntityStorageIdentityConnector {
|
|
|
470
560
|
}
|
|
471
561
|
/**
|
|
472
562
|
* Check a verifiable credential is valid.
|
|
473
|
-
* @param
|
|
563
|
+
* @param credential The credential to verify.
|
|
474
564
|
* @returns The credential stored in the jwt and the revocation status.
|
|
475
565
|
*/
|
|
476
|
-
async checkVerifiableCredential(
|
|
477
|
-
|
|
566
|
+
async checkVerifiableCredential(credential) {
|
|
567
|
+
if (Is.object(credential)) {
|
|
568
|
+
Guards.objectValue(EntityStorageIdentityConnector.CLASS_NAME, "credential", credential);
|
|
569
|
+
Guards.objectValue(EntityStorageIdentityConnector.CLASS_NAME, "credential.proof", credential.proof);
|
|
570
|
+
const { proof, ...doc } = credential;
|
|
571
|
+
await this.verifyProof(JsonLdHelper.toNodeObject(doc), ArrayHelper.fromObjectOrArray(proof)[0]);
|
|
572
|
+
return {
|
|
573
|
+
revoked: false,
|
|
574
|
+
verifiableCredential: doc
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
Guards.stringValue(EntityStorageIdentityConnector.CLASS_NAME, "credential", credential);
|
|
478
578
|
try {
|
|
479
|
-
const jwtDecoded = await Jwt.decode(
|
|
579
|
+
const jwtDecoded = await Jwt.decode(credential);
|
|
480
580
|
const jwtHeader = jwtDecoded.header;
|
|
481
581
|
const jwtPayload = jwtDecoded.payload;
|
|
482
582
|
const jwtSignature = jwtDecoded.signature;
|
|
@@ -511,7 +611,7 @@ export class EntityStorageIdentityConnector {
|
|
|
511
611
|
method: jwtHeader.kid
|
|
512
612
|
});
|
|
513
613
|
}
|
|
514
|
-
await Jwt.verifySignature(
|
|
614
|
+
await Jwt.verifySignature(credential, await Jwk.toCryptoKey(didMethod.publicKeyJwk));
|
|
515
615
|
const verifiableCredential = jwtPayload.vc;
|
|
516
616
|
if (Is.object(verifiableCredential)) {
|
|
517
617
|
if (Is.string(jwtPayload.jti)) {
|
|
@@ -641,11 +741,12 @@ export class EntityStorageIdentityConnector {
|
|
|
641
741
|
* @param contexts The contexts for the data stored in the verifiable credential.
|
|
642
742
|
* @param types The types for the data stored in the verifiable credential.
|
|
643
743
|
* @param verifiableCredentials The credentials to use for creating the presentation in jwt format.
|
|
644
|
-
* @param
|
|
744
|
+
* @param options Additional options for creating the verifiable presentation.
|
|
745
|
+
* @param options.expirationDate The date the verifiable presentation is valid until.
|
|
645
746
|
* @returns The created verifiable presentation and its token.
|
|
646
747
|
* @throws NotFoundError if the id can not be resolved.
|
|
647
748
|
*/
|
|
648
|
-
async createVerifiablePresentation(controller, verificationMethodId, presentationId, contexts, types, verifiableCredentials,
|
|
749
|
+
async createVerifiablePresentation(controller, verificationMethodId, presentationId, contexts, types, verifiableCredentials, options) {
|
|
649
750
|
Guards.stringValue(EntityStorageIdentityConnector.CLASS_NAME, "controller", controller);
|
|
650
751
|
Guards.stringValue(EntityStorageIdentityConnector.CLASS_NAME, "verificationMethodId", verificationMethodId);
|
|
651
752
|
if (Is.array(types)) {
|
|
@@ -655,8 +756,8 @@ export class EntityStorageIdentityConnector {
|
|
|
655
756
|
Guards.stringValue(EntityStorageIdentityConnector.CLASS_NAME, "types", types);
|
|
656
757
|
}
|
|
657
758
|
Guards.arrayValue(EntityStorageIdentityConnector.CLASS_NAME, "verifiableCredentials", verifiableCredentials);
|
|
658
|
-
if (!Is.undefined(
|
|
659
|
-
Guards.
|
|
759
|
+
if (!Is.undefined(options?.expirationDate)) {
|
|
760
|
+
Guards.date(EntityStorageIdentityConnector.CLASS_NAME, "options.expirationDate", options.expirationDate);
|
|
660
761
|
}
|
|
661
762
|
try {
|
|
662
763
|
const idParts = DocumentHelper.parseId(verificationMethodId);
|
|
@@ -694,8 +795,10 @@ export class EntityStorageIdentityConnector {
|
|
|
694
795
|
else if (Is.stringValue(types)) {
|
|
695
796
|
finalTypes.push(types);
|
|
696
797
|
}
|
|
798
|
+
const combinedContext = JsonLdProcessor.combineContexts(DidContexts.ContextVCv1, contexts) ??
|
|
799
|
+
DidContexts.ContextVCv1;
|
|
697
800
|
const verifiablePresentation = {
|
|
698
|
-
"@context":
|
|
801
|
+
"@context": combinedContext,
|
|
699
802
|
id: presentationId,
|
|
700
803
|
type: finalTypes,
|
|
701
804
|
verifiableCredential: verifiableCredentials,
|
|
@@ -704,21 +807,23 @@ export class EntityStorageIdentityConnector {
|
|
|
704
807
|
const jwtHeader = {
|
|
705
808
|
kid: didMethod.id,
|
|
706
809
|
typ: "JWT",
|
|
707
|
-
alg:
|
|
810
|
+
alg: JwsAlgorithms.EdDSA
|
|
708
811
|
};
|
|
709
812
|
const jwtVp = ObjectHelper.pick(ObjectHelper.clone(verifiablePresentation), [
|
|
710
813
|
"@context",
|
|
711
814
|
"type",
|
|
712
815
|
"verifiableCredential"
|
|
713
816
|
]);
|
|
817
|
+
// Add the proof to the VP after extracting the jwt data
|
|
818
|
+
// as the jwt does not include the proof
|
|
819
|
+
verifiablePresentation.proof = await this.createProof(controller, verificationMethodId, ProofTypes.DataIntegrityProof, JsonLdHelper.toNodeObject(verifiablePresentation));
|
|
714
820
|
const jwtPayload = {
|
|
715
|
-
iss:
|
|
821
|
+
iss: verifiablePresentation.holder,
|
|
716
822
|
nbf: Math.floor(Date.now() / 1000),
|
|
717
823
|
vp: jwtVp
|
|
718
824
|
};
|
|
719
|
-
if (Is.
|
|
720
|
-
|
|
721
|
-
jwtPayload.exp = Math.floor(Date.now() / 1000) + expiresInSeconds;
|
|
825
|
+
if (Is.date(options?.expirationDate)) {
|
|
826
|
+
jwtPayload.exp = Math.floor(options.expirationDate.getTime() / 1000);
|
|
722
827
|
}
|
|
723
828
|
const signature = await Jwt.encodeWithSigner(jwtHeader, jwtPayload, async (header, payload) => VaultConnectorHelper.jwtSigner(this._vaultConnector, EntityStorageIdentityConnector.buildVaultKey(idParts.id, idParts.fragment ?? ""), header, payload));
|
|
724
829
|
return {
|
|
@@ -732,11 +837,19 @@ export class EntityStorageIdentityConnector {
|
|
|
732
837
|
}
|
|
733
838
|
/**
|
|
734
839
|
* Check a verifiable presentation is valid.
|
|
735
|
-
* @param
|
|
840
|
+
* @param presentation The presentation to verify.
|
|
736
841
|
* @returns The presentation stored in the jwt and the revocation status.
|
|
737
842
|
*/
|
|
738
|
-
async checkVerifiablePresentation(
|
|
739
|
-
|
|
843
|
+
async checkVerifiablePresentation(presentation) {
|
|
844
|
+
if (Is.object(presentation)) {
|
|
845
|
+
const { proof, ...doc } = presentation;
|
|
846
|
+
const proofEntry = ArrayHelper.fromObjectOrArray(proof)[0];
|
|
847
|
+
Guards.objectValue(EntityStorageIdentityConnector.CLASS_NAME, "proofEntry", proofEntry);
|
|
848
|
+
await this.verifyProof(JsonLdHelper.toNodeObject(doc), proofEntry);
|
|
849
|
+
return { revoked: false, verifiablePresentation: doc };
|
|
850
|
+
}
|
|
851
|
+
Guards.stringValue(EntityStorageIdentityConnector.CLASS_NAME, "presentation", presentation);
|
|
852
|
+
const presentationJwt = presentation;
|
|
740
853
|
try {
|
|
741
854
|
const jwtDecoded = await Jwt.decode(presentationJwt);
|
|
742
855
|
const jwtHeader = jwtDecoded.header;
|
|
@@ -821,11 +934,15 @@ export class EntityStorageIdentityConnector {
|
|
|
821
934
|
}
|
|
822
935
|
/**
|
|
823
936
|
* Create a proof for arbitrary data with the specified verification method.
|
|
937
|
+
* This method uses async signing to ensure the private key never leaves the vault,
|
|
938
|
+
* with algorithm validation to ensure key type compatibility.
|
|
824
939
|
* @param controller The controller of the identity who can make changes.
|
|
825
940
|
* @param verificationMethodId The verification method id to use.
|
|
826
941
|
* @param proofType The type of proof to create.
|
|
827
942
|
* @param unsecureDocument The unsecure document to create the proof for.
|
|
828
943
|
* @returns The proof.
|
|
944
|
+
* @throws NotFoundError if the identity or method is not found.
|
|
945
|
+
* @throws GeneralError if algorithm doesn't match key type or proof creation fails.
|
|
829
946
|
*/
|
|
830
947
|
async createProof(controller, verificationMethodId, proofType, unsecureDocument) {
|
|
831
948
|
Guards.stringValue(EntityStorageIdentityConnector.CLASS_NAME, "controller", controller);
|
|
@@ -862,8 +979,14 @@ export class EntityStorageIdentityConnector {
|
|
|
862
979
|
});
|
|
863
980
|
}
|
|
864
981
|
const vaultKey = EntityStorageIdentityConnector.buildVaultKey(didDocument.id, idParts.fragment ?? "");
|
|
865
|
-
const
|
|
866
|
-
|
|
982
|
+
const keyType = await this._vaultConnector.getKeyType(vaultKey);
|
|
983
|
+
if (Is.undefined(keyType)) {
|
|
984
|
+
throw new GeneralError(EntityStorageIdentityConnector.CLASS_NAME, "privateKeyMissing", {
|
|
985
|
+
keyId: vaultKey
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
const unsignedProof = ProofHelper.createUnsignedProof(proofType, verificationMethodId);
|
|
989
|
+
const signedProof = await ProofHelper.createProofWithSigner(proofType, unsecureDocument, unsignedProof, async (data, algorithm) => this.signWithVault(vaultKey, keyType, data, algorithm));
|
|
867
990
|
return signedProof;
|
|
868
991
|
}
|
|
869
992
|
catch (error) {
|
|
@@ -916,6 +1039,27 @@ export class EntityStorageIdentityConnector {
|
|
|
916
1039
|
throw new GeneralError(EntityStorageIdentityConnector.CLASS_NAME, "verifyProofFailed", undefined, error);
|
|
917
1040
|
}
|
|
918
1041
|
}
|
|
1042
|
+
/**
|
|
1043
|
+
* Signs data using the vault connector with algorithm validation.
|
|
1044
|
+
* @param vaultKey The vault key identifier.
|
|
1045
|
+
* @param keyType The type of the key.
|
|
1046
|
+
* @param data The data to sign.
|
|
1047
|
+
* @param algorithm The signing algorithm.
|
|
1048
|
+
* @returns The signature bytes.
|
|
1049
|
+
* @throws GeneralError if algorithm doesn't match key type.
|
|
1050
|
+
* @internal
|
|
1051
|
+
*/
|
|
1052
|
+
async signWithVault(vaultKey, keyType, data, algorithm) {
|
|
1053
|
+
if (algorithm === JwsAlgorithms.EdDSA && keyType !== VaultKeyType.Ed25519) {
|
|
1054
|
+
throw new GeneralError(EntityStorageIdentityConnector.CLASS_NAME, "algorithmKeyTypeMismatch", {
|
|
1055
|
+
algorithm,
|
|
1056
|
+
expectedKeyType: VaultKeyType.Ed25519,
|
|
1057
|
+
actualKeyType: keyType,
|
|
1058
|
+
keyId: vaultKey
|
|
1059
|
+
});
|
|
1060
|
+
}
|
|
1061
|
+
return this._vaultConnector.sign(vaultKey, data);
|
|
1062
|
+
}
|
|
919
1063
|
/**
|
|
920
1064
|
* Get all the methods from a document.
|
|
921
1065
|
* @param document The document to get the methods from.
|