diff --git a/__tests__/shared/credentialStatus.ts b/__tests__/shared/credentialStatus.ts index 4dcda0b9be..d69c78b60d 100644 --- a/__tests__/shared/credentialStatus.ts +++ b/__tests__/shared/credentialStatus.ts @@ -102,9 +102,9 @@ export default (testContext: { }) expect(vc).toHaveProperty('proof.jwt') - const verified = await agent.verifyCredential({ credential: vc }) + const result = await agent.verifyCredential({ credential: vc }) expect(callsCounter).toHaveBeenCalledTimes(1) - expect(verified).toBeTruthy() + expect(result.verified).toEqual(true) }) it('should check credentialStatus for revoked JWT credential', async () => { @@ -114,9 +114,9 @@ export default (testContext: { }) expect(vc).toHaveProperty('proof.jwt') - const verified = await agent.verifyCredential({ credential: vc }) + const result = await agent.verifyCredential({ credential: vc }) expect(callsCounter).toHaveBeenCalledTimes(1) - expect(verified).toBeFalsy() + expect(result.verified).toEqual(false) }) it('should fail checking credentialStatus with exception during verification', async () => { @@ -152,9 +152,9 @@ export default (testContext: { }) expect(vc).toHaveProperty('proof.jws') - const verified = await agent.verifyCredential({ credential: vc }) + const result = await agent.verifyCredential({ credential: vc }) expect(callsCounter).toHaveBeenCalledTimes(1) - expect(verified).toBeTruthy() + expect(result.verified).toEqual(true) }) it('should check credentialStatus for revoked JSON-LD credential', async () => { @@ -164,9 +164,9 @@ export default (testContext: { }) expect(vc).toHaveProperty('proof.jws') - const verified = await agent.verifyCredential({ credential: vc }) + const result = await agent.verifyCredential({ credential: vc }) expect(callsCounter).toHaveBeenCalledTimes(1) - expect(verified).toBeFalsy() + expect(result.verified).toEqual(false) }) it('should check credentialStatus for EIP712 credential', async () => { @@ -176,9 +176,9 @@ export default (testContext: { }) expect(vc).toHaveProperty('proof.proofValue') - const verified = await agent.verifyCredential({ credential: vc }) + const result = await agent.verifyCredential({ credential: vc }) expect(callsCounter).toHaveBeenCalledTimes(1) - expect(verified).toBeTruthy() + expect(result.verified).toEqual(true) }) it('should check credentialStatus for revoked EIP712 credential', async () => { @@ -188,9 +188,9 @@ export default (testContext: { }) expect(vc).toHaveProperty('proof.proofValue') - const verified = await agent.verifyCredential({ credential: vc }) + const result = await agent.verifyCredential({ credential: vc }) expect(callsCounter).toHaveBeenCalledTimes(1) - expect(verified).toBeFalsy() + expect(result.verified).toEqual(false) }) }) @@ -235,7 +235,7 @@ export default (testContext: { // TODO It`s an exception flow an it'd be better to throw an exception instead of returning false await expect(agent.verifyCredential({ credential: vc })).rejects.toThrow( - `The credential status can't be verified by the agent`, + `invalid_config: The credential status can't be verified because there is no ICredentialStatusVerifier plugin installed.`, ) }) }) diff --git a/__tests__/shared/verifiableDataLD.ts b/__tests__/shared/verifiableDataLD.ts index 778221f898..8cea4f4aed 100644 --- a/__tests__/shared/verifiableDataLD.ts +++ b/__tests__/shared/verifiableDataLD.ts @@ -72,7 +72,7 @@ export default (testContext: { credential: verifiableCredential, }) - expect(result).toEqual(true) + expect(result.verified).toEqual(true) }) it('should handleMessage with VC (non-JWT)', async () => { @@ -98,20 +98,19 @@ export default (testContext: { hash: storedCredentialHash, }) + // tamper with credential verifiableCredential.credentialSubject.name = 'Martin, the not so greats' - try { - await agent.handleMessage({ + await expect( + agent.handleMessage({ raw: JSON.stringify({ body: verifiableCredential, type: 'w3c.vc', }), save: false, metaData: [{ type: 'LDS' }], - }) - } catch (e) { - expect(e).toEqual(Error('Error verifying LD Verifiable Credential')) - } + }), + ).rejects.toThrow(/Verification error/) }) it('should sign a verifiable presentation in LD', async () => { @@ -164,7 +163,7 @@ export default (testContext: { domain, }) - expect(result).toBeTruthy() + expect(result.verified).toEqual(true) }) it('should handleMessage with VPs (non-JWT)', async () => { @@ -244,7 +243,7 @@ export default (testContext: { credential: verifiableCredential, }) - expect(result).toEqual(true) + expect(result.verified).toEqual(true) }) }) } diff --git a/packages/cli/src/credential.ts b/packages/cli/src/credential.ts index fe6806f77d..aec46f3801 100644 --- a/packages/cli/src/credential.ts +++ b/packages/cli/src/credential.ts @@ -191,7 +191,7 @@ credential } try { const result = await agent.verifyCredential({ credential: credentialAsJSON }) - if (result === true) { + if (result.verified === true) { console.log('Credential was verified successfully.') } else { console.error('Credential could not be verified.') diff --git a/packages/core/package.json b/packages/core/package.json index 296f6d5175..1853aac784 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -23,14 +23,14 @@ }, "dependencies": { "debug": "^4.3.3", - "did-jwt-vc": "^2.1.14", + "did-jwt-vc": "3.0.1", "events": "^3.2.0", "z-schema": "^5.0.2" }, "devDependencies": { "@types/debug": "4.1.7", - "did-resolver": "^4.0.0", - "credential-status": "^2.0.5", + "credential-status": "2.0.5", + "did-resolver": "4.0.0", "typescript": "4.7.3" }, "files": [ diff --git a/packages/credential-eip712/src/agent/CredentialEIP712.ts b/packages/credential-eip712/src/agent/CredentialEIP712.ts index d7da2be918..fdfa50ba03 100644 --- a/packages/credential-eip712/src/agent/CredentialEIP712.ts +++ b/packages/credential-eip712/src/agent/CredentialEIP712.ts @@ -1,13 +1,21 @@ import { - CredentialPayload, IAgentPlugin, IIdentifier, PresentationPayload, VerifiableCredential, VerifiablePresentation -} from "@veramo/core" + CredentialPayload, + IAgentPlugin, + IIdentifier, + PresentationPayload, + VerifiableCredential, + VerifiablePresentation, +} from '@veramo/core' import { - extractIssuer, getChainIdForDidEthr, + extractIssuer, + getChainIdForDidEthr, getEthereumAddress, isDefined, - MANDATORY_CREDENTIAL_CONTEXT, mapIdentifierKeysToDoc, processEntryToArray, - resolveDidOrThrow -} from "@veramo/utils" + MANDATORY_CREDENTIAL_CONTEXT, + mapIdentifierKeysToDoc, + processEntryToArray, + resolveDidOrThrow, +} from '@veramo/utils' import { schema } from '../index' import { recoverTypedSignature, SignTypedDataVersion } from '@metamask/eth-sig-util' @@ -17,10 +25,10 @@ import { ICredentialIssuerEIP712, IRequiredContext, IVerifyCredentialEIP712Args, - IVerifyPresentationEIP712Args + IVerifyPresentationEIP712Args, } from '../types/ICredentialEIP712' -import { getEthTypesFromInputDoc } from "eip-712-types-generation" +import { getEthTypesFromInputDoc } from 'eip-712-types-generation' /** * A Veramo plugin that implements the {@link ICredentialIssuerEIP712} methods. @@ -36,7 +44,7 @@ export class CredentialIssuerEIP712 implements IAgentPlugin { createVerifiableCredentialEIP712: this.createVerifiableCredentialEIP712.bind(this), createVerifiablePresentationEIP712: this.createVerifiablePresentationEIP712.bind(this), verifyCredentialEIP712: this.verifyCredentialEIP712.bind(this), - verifyPresentationEIP712: this.verifyPresentationEIP712.bind(this) + verifyPresentationEIP712: this.verifyPresentationEIP712.bind(this), } } @@ -57,7 +65,7 @@ export class CredentialIssuerEIP712 implements IAgentPlugin { const issuer = extractIssuer(args.credential) if (!issuer || typeof issuer === 'undefined') { - throw new Error('invalid_argument: args.credential.issuer must not be empty') + throw new Error('invalid_argument: credential.issuer must not be empty') } let keyRef = args.keyRef @@ -65,14 +73,17 @@ export class CredentialIssuerEIP712 implements IAgentPlugin { const identifier = await context.agent.didManagerGet({ did: issuer }) if (!keyRef) { - const key = identifier.keys.find((k) => k.type === 'Secp256k1' && k.meta?.algorithms?.includes('eth_signTypedData')) - if (!key) throw Error('No signing key for ' + identifier.did) + const key = identifier.keys.find( + (k) => k.type === 'Secp256k1' && k.meta?.algorithms?.includes('eth_signTypedData'), + ) + if (!key) throw Error('key_not_found: No suitable signing key is known for ' + identifier.did) keyRef = key.kid } const extendedKeys = await mapIdentifierKeysToDoc(identifier, 'verificationMethod', context) - const extendedKey = extendedKeys.find(key => key.kid === keyRef) - if (!extendedKey) throw Error('Key not found') + const extendedKey = extendedKeys.find((key) => key.kid === keyRef) + if (!extendedKey) + throw Error('key_not_found: The signing key is not available in the issuer DID document') const chainId = getChainIdForDidEthr(extendedKey.meta.verificationMethod) @@ -84,72 +95,73 @@ export class CredentialIssuerEIP712 implements IAgentPlugin { proof: { verificationMethod: extendedKey.meta.verificationMethod.id, created: issuanceDate, - proofPurpose: "assertionMethod", - type: "EthereumEip712Signature2021", - } + proofPurpose: 'assertionMethod', + type: 'EthereumEip712Signature2021', + }, } - const message = credential; + const message = credential const domain = { chainId, - name: "VerifiableCredential", - version: "1", - }; + name: 'VerifiableCredential', + version: '1', + } - const primaryType = "VerifiableCredential" - const allTypes = getEthTypesFromInputDoc(credential, primaryType); + const primaryType = 'VerifiableCredential' + const allTypes = getEthTypesFromInputDoc(credential, primaryType) const types = { ...allTypes } const data = JSON.stringify({ domain, types, message, primaryType }) const signature = await context.agent.keyManagerSign({ keyRef, data, algorithm: 'eth_signTypedData' }) - credential['proof']['proofValue'] = signature; + credential['proof']['proofValue'] = signature credential['proof']['eip712'] = { domain, messageSchema: allTypes, primaryType, } - return credential as VerifiableCredential; + return credential as VerifiableCredential } /** {@inheritdoc ICredentialIssuerEIP712.verifyCredentialEIP712} */ - private async verifyCredentialEIP712(args: IVerifyCredentialEIP712Args, context: IRequiredContext): Promise { + private async verifyCredentialEIP712( + args: IVerifyCredentialEIP712Args, + context: IRequiredContext, + ): Promise { const { credential } = args - if (!credential.proof || !credential.proof.proofValue) throw new Error("Proof is undefined") - if ( - !credential.proof.eip712 || - !credential.proof.eip712.messageSchema || - !credential.proof.eip712.domain - ) throw new Error("eip712 is undefined"); + if (!credential.proof || !credential.proof.proofValue) + throw new Error('invalid_argument: proof is undefined') + if (!credential.proof.eip712 || !credential.proof.eip712.messageSchema || !credential.proof.eip712.domain) + throw new Error('invalid_argument: proof.eip712 is missing expected properties') - const { proof, ...signingInput } = credential; - const { proofValue, eip712, ...verifyInputProof } = proof; + const { proof, ...signingInput } = credential + const { proofValue, eip712, ...verifyInputProof } = proof const verificationMessage = { ...signingInput, - proof: verifyInputProof + proof: verifyInputProof, } const objectToVerify = { message: verificationMessage, domain: eip712.domain, types: eip712.messageSchema, - primaryType: eip712.primaryType + primaryType: eip712.primaryType, } const recovered = recoverTypedSignature({ data: objectToVerify, signature: proofValue, - version: SignTypedDataVersion.V4 + version: SignTypedDataVersion.V4, }) const issuer = extractIssuer(credential) if (!issuer || typeof issuer === 'undefined') { - throw new Error('invalid_argument: args.credential.issuer must not be empty') + throw new Error('invalid_argument: credential.issuer must not be empty') } - const didDocument = await resolveDidOrThrow(issuer, context); + const didDocument = await resolveDidOrThrow(issuer, context) if (didDocument.verificationMethod) { for (const verificationMethod of didDocument.verificationMethod) { @@ -157,12 +169,11 @@ export class CredentialIssuerEIP712 implements IAgentPlugin { return true } } - } - else { - throw new Error("Recovered Address does not match issuer") + } else { + throw new Error('resolver_error: issuer DIDDocument does not contain any verificationMethods') } - return true; + return false } /** {@inheritdoc ICredentialIssuerEIP712.createVerifiablePresentationEIP712} */ @@ -188,7 +199,7 @@ export class CredentialIssuerEIP712 implements IAgentPlugin { } if (!isDefined(args.presentation.holder)) { - throw new Error('invalid_argument: args.presentation.holder must not be empty') + throw new Error('invalid_argument: presentation.holder must not be empty') } if (args.presentation.verifiableCredential) { @@ -207,105 +218,109 @@ export class CredentialIssuerEIP712 implements IAgentPlugin { try { identifier = await context.agent.didManagerGet({ did: presentation.holder }) } catch (e) { - throw new Error('invalid_argument: args.presentation.holder must be a DID managed by this agent') + throw new Error('invalid_argument: presentation.holder must be a DID managed by this agent') } let keyRef = args.keyRef if (!keyRef) { - const key = identifier.keys.find((k) => k.type === 'Secp256k1' && k.meta?.algorithms?.includes('eth_signTypedData')) - if (!key) throw Error('No signing key for ' + identifier.did) + const key = identifier.keys.find( + (k) => k.type === 'Secp256k1' && k.meta?.algorithms?.includes('eth_signTypedData'), + ) + if (!key) throw Error('key_not_found: No suitable signing key is known for ' + identifier.did) keyRef = key.kid } const extendedKeys = await mapIdentifierKeysToDoc(identifier, 'verificationMethod', context) - const extendedKey = extendedKeys.find(key => key.kid === keyRef) - if (!extendedKey) throw Error('Key not found') + const extendedKey = extendedKeys.find((key) => key.kid === keyRef) + if (!extendedKey) + throw Error('key_not_found: The signing key is not available in the issuer DID document') const chainId = getChainIdForDidEthr(extendedKey.meta.verificationMethod) presentation['proof'] = { verificationMethod: extendedKey.meta.verificationMethod.id, created: issuanceDate, - proofPurpose: "assertionMethod", - type: "EthereumEip712Signature2021", + proofPurpose: 'assertionMethod', + type: 'EthereumEip712Signature2021', } - const message = presentation; + const message = presentation const domain = { chainId, - name: "VerifiablePresentation", - version: "1", - }; + name: 'VerifiablePresentation', + version: '1', + } const primaryType = 'VerifiablePresentation' - const allTypes = getEthTypesFromInputDoc(presentation, primaryType); + const allTypes = getEthTypesFromInputDoc(presentation, primaryType) const types = { ...allTypes } const data = JSON.stringify({ domain, types, message }) const signature = await context.agent.keyManagerSign({ keyRef, data, algorithm: 'eth_signTypedData' }) - - presentation.proof.proofValue = signature; + presentation.proof.proofValue = signature presentation.proof.eip712 = { domain, messageSchema: allTypes, primaryType, - }; + } return presentation as VerifiablePresentation } /** {@inheritdoc ICredentialIssuerEIP712.verifyPresentationEIP712} */ - private async verifyPresentationEIP712(args: IVerifyPresentationEIP712Args, context: IRequiredContext): Promise { - try { - const { presentation } = args - if (!presentation.proof || !presentation.proof.proofValue) throw new Error("Proof is undefined") - if ( - !presentation.proof.eip712 || - !presentation.proof.eip712.messageSchema || - !presentation.proof.eip712.domain - ) throw new Error("eip712 is undefined"); - - const { proof, ...signingInput } = presentation; - const { proofValue, eip712, ...verifyInputProof } = proof; - const verificationMessage = { - ...signingInput, - proof: verifyInputProof - } + private async verifyPresentationEIP712( + args: IVerifyPresentationEIP712Args, + context: IRequiredContext, + ): Promise { + const { presentation } = args + if (!presentation.proof || !presentation.proof.proofValue) throw new Error('Proof is undefined') + if ( + !presentation.proof.eip712 || + !presentation.proof.eip712.messageSchema || + !presentation.proof.eip712.domain + ) + throw new Error('proof.eip712 is undefined') - const objectToVerify = { - message: verificationMessage, - domain: eip712.domain, - types: eip712.messageSchema, - primaryType: eip712.primaryType - } + const { proof, ...signingInput } = presentation + const { proofValue, eip712, ...verifyInputProof } = proof + const verificationMessage = { + ...signingInput, + proof: verifyInputProof, + } - const recovered = recoverTypedSignature({ - data: objectToVerify, - signature: proofValue, - version: SignTypedDataVersion.V4 - }) + const objectToVerify = { + message: verificationMessage, + domain: eip712.domain, + types: eip712.messageSchema, + primaryType: eip712.primaryType, + } - const issuer = extractIssuer(presentation) - if (!issuer || typeof issuer === 'undefined') { - throw new Error('invalid_argument: args.presentation.issuer must not be empty') - } + const recovered = recoverTypedSignature({ + data: objectToVerify, + signature: proofValue, + version: SignTypedDataVersion.V4, + }) - const didDocument = await resolveDidOrThrow(issuer, context); + const issuer = extractIssuer(presentation) + if (!issuer || typeof issuer === 'undefined') { + throw new Error('invalid_argument: args.presentation.issuer must not be empty') + } + + const didDocument = await resolveDidOrThrow(issuer, context) - if (didDocument.verificationMethod) { - for (const verificationMethod of didDocument.verificationMethod) { - if (getEthereumAddress(verificationMethod)?.toLowerCase() === recovered.toLowerCase()) { - return true - } + if (didDocument.verificationMethod) { + for (const verificationMethod of didDocument.verificationMethod) { + if (getEthereumAddress(verificationMethod)?.toLowerCase() === recovered.toLowerCase()) { + return true } } - - throw new Error("Recovered Address does not match issuer") - } catch (e: any) { - throw new Error(e); + } else { + throw new Error('resolver_error: holder DIDDocument does not contain any verificationMethods') } + + return false } } diff --git a/packages/credential-ld/src/__tests__/issue-verify-flow.test.ts b/packages/credential-ld/src/__tests__/issue-verify-flow.test.ts index 22303c8da6..7f57baa481 100644 --- a/packages/credential-ld/src/__tests__/issue-verify-flow.test.ts +++ b/packages/credential-ld/src/__tests__/issue-verify-flow.test.ts @@ -91,11 +91,11 @@ describe('credential-LD full flow', () => { expect(verifiableCredential).toBeDefined() - const verified = await agent.verifyCredential({ + const result = await agent.verifyCredential({ credential: verifiableCredential, }) - expect(verified).toBe(true) + expect(result.verified).toBe(true) }) it('works with EcdsaSecp256k1RecoveryMethod2020 credentials', async () => { @@ -113,11 +113,11 @@ describe('credential-LD full flow', () => { expect(verifiableCredential).toBeDefined() - const verified = await agent.verifyCredential({ + const result = await agent.verifyCredential({ credential: verifiableCredential, }) - expect(verified).toBe(true) + expect(result.verified).toBe(true) }) it('works with Ed25519Signature2018 credential and presentation', async () => { @@ -144,12 +144,12 @@ describe('credential-LD full flow', () => { expect(verifiablePresentation).toBeDefined() - const verified = await agent.verifyPresentation({ + const result = await agent.verifyPresentation({ presentation: verifiablePresentation, challenge: 'VERAMO', }) - expect(verified).toBe(true) + expect(result.verified).toBe(true) }) it('works with EcdsaSecp256k1RecoveryMethod2020 credential and presentation', async () => { @@ -179,11 +179,11 @@ describe('credential-LD full flow', () => { expect(verifiablePresentation).toBeDefined() - const verified = await agent.verifyPresentation({ + const result = await agent.verifyPresentation({ presentation: verifiablePresentation, challenge: 'VERAMO', }) - expect(verified).toBe(true) + expect(result.verified).toBe(true) }) }) diff --git a/packages/credential-ld/src/ld-credential-module.ts b/packages/credential-ld/src/ld-credential-module.ts index 217c831916..e171da360e 100644 --- a/packages/credential-ld/src/ld-credential-module.ts +++ b/packages/credential-ld/src/ld-credential-module.ts @@ -28,6 +28,7 @@ export class LdCredentialModule { private ldContextLoader: LdContextLoader ldSuiteLoader: LdSuiteLoader + constructor(options: { ldContextLoader: LdContextLoader; ldSuiteLoader: LdSuiteLoader }) { this.ldContextLoader = options.ldContextLoader this.ldSuiteLoader = options.ldSuiteLoader @@ -150,13 +151,12 @@ export class LdCredentialModule { checkStatus: async () => Promise.resolve({ verified: true }), // Fake method }) - if (result.verified) return true + if (!result.verified) { + // result can include raw Error + debug(`Error verifying LD Credential: ${JSON.stringify(result, null, 2)}`) + } - // NOT verified. - // result can include raw Error - debug(`Error verifying LD Verifiable Credential: ${JSON.stringify(result, null, 2)}`) - // console.log(JSON.stringify(result, null, 2)); - throw Error('Error verifying LD Verifiable Credential') + return result } async verifyPresentation( @@ -175,13 +175,10 @@ export class LdCredentialModule { compactProof: false, }) - if (result.verified) return true - - // NOT verified. - - // result can include raw Error - console.log(`Error verifying LD Verifiable Presentation`) - console.log(JSON.stringify(result, null, 2)) - throw Error('Error verifying LD Verifiable Presentation') + if (!result.verified) { + // result can include raw Error + debug(`Error verifying LD Presentation: ${JSON.stringify(result, null, 2)}`) + } + return result } } diff --git a/packages/credential-status/package.json b/packages/credential-status/package.json index ce0bf5797a..a8a83fb9e8 100644 --- a/packages/credential-status/package.json +++ b/packages/credential-status/package.json @@ -12,7 +12,7 @@ "@veramo/core": "^3.1.0", "@veramo/utils": "^3.1.0", "credential-status": "^2.0.5", - "did-jwt": "^6.3.0", + "did-jwt": "^6.5.0", "did-resolver": "^4.0.0" }, "devDependencies": { diff --git a/packages/credential-w3c/package.json b/packages/credential-w3c/package.json index b7fbb6fe9c..f9933babcd 100644 --- a/packages/credential-w3c/package.json +++ b/packages/credential-w3c/package.json @@ -20,7 +20,7 @@ "@veramo/message-handler": "^3.1.4", "@veramo/utils": "^3.1.4", "debug": "^4.3.3", - "did-jwt-vc": "^2.1.14", + "did-jwt-vc": "3.0.1", "did-resolver": "^4.0.0", "uint8arrays": "^3.0.0", "uuid": "^8.3.0" diff --git a/packages/credential-w3c/plugin.schema.json b/packages/credential-w3c/plugin.schema.json index 6a6ebcd4d4..08b1c277fc 100644 --- a/packages/credential-w3c/plugin.schema.json +++ b/packages/credential-w3c/plugin.schema.json @@ -368,84 +368,51 @@ "$ref": "#/components/schemas/W3CVerifiableCredential", "description": "The Verifiable Credential object according to the\n {@link https://www.w3.org/TR/vc-data-model/#credentials | canonical model } or the JWT representation.\n\nThe signer of the Credential is verified based on the `issuer.id` property of the `credential` or the `iss` property of the JWT payload respectively" }, - "fetchRemoteContexts": { - "type": "boolean", - "description": "When dealing with JSON-LD you also MUST provide the proper contexts. Set this to `true` ONLY if you want the '@context' URLs to be fetched in case they are not pre-loaded. The context definitions SHOULD rather be provided at startup instead of being fetched.", - "default": false - } - }, - "required": [ - "credential" - ], - "additionalProperties": { - "description": "Other options can be specified for verification. They will be forwarded to the lower level modules. that performt the checks" - }, - "description": "Encapsulates the parameters required to verify a\n {@link https://www.w3.org/TR/vc-data-model/#credentials | W3C Verifiable Credential }" - }, - "IVerifyPresentationArgs": { - "type": "object", - "properties": { - "presentation": { - "$ref": "#/components/schemas/W3CVerifiablePresentation", - "description": "The Verifiable Presentation object according to the\n {@link https://www.w3.org/TR/vc-data-model/#presentations | canonical model } or the JWT representation.\n\nThe signer of the Presentation is verified based on the `holder` property of the `presentation` or the `iss` property of the JWT payload respectively" - }, - "challenge": { - "type": "string", - "description": "Optional (only for JWT) string challenge parameter to verify the verifiable presentation against" - }, - "domain": { - "type": "string", - "description": "Optional (only for JWT) string domain parameter to verify the verifiable presentation against" - }, "fetchRemoteContexts": { "type": "boolean", "description": "When dealing with JSON-LD you also MUST provide the proper contexts. Set this to `true` ONLY if you want the '@context' URLs to be fetched in case they are not pre-loaded. The context definitions SHOULD rather be provided at startup instead of being fetched.", "default": false }, "policies": { - "$ref": "#/components/schemas/VerifyPresentationPolicies", - "description": "Verification Policies for the verifiable presentation These will also be forwarded to the lower level module" + "$ref": "#/components/schemas/VerificationPolicies", + "description": "Overrides specific aspects of credential verification, where possible." } }, "required": [ - "presentation" + "credential" ], "additionalProperties": { "description": "Other options can be specified for verification. They will be forwarded to the lower level modules. that performt the checks" }, - "description": "Encapsulates the parameters required to verify a\n {@link https://www.w3.org/TR/vc-data-model/#presentations | W3C Verifiable Presentation }" - }, - "W3CVerifiablePresentation": { - "anyOf": [ - { - "$ref": "#/components/schemas/VerifiablePresentation" - }, - { - "$ref": "#/components/schemas/CompactJWT" - } - ], - "description": "Represents a signed Verifiable Presentation (includes proof) in either JSON or compact JWT format. See {@link https://www.w3.org/TR/vc-data-model/#credentials | VC data model }" + "description": "Encapsulates the parameters required to verify a\n {@link https://www.w3.org/TR/vc-data-model/#credentials | W3C Verifiable Credential }" }, - "VerifyPresentationPolicies": { + "VerificationPolicies": { "type": "object", "properties": { "now": { "type": "number", - "description": "policy to over the now (current time) during the verification check" + "description": "policy to over the now (current time) during the verification check (UNIX time in seconds)" }, "issuanceDate": { "type": "boolean", - "description": "policy to override the issuanceDate (nbf) timestamp check" + "description": "policy to skip the issuanceDate (nbf) timestamp check when set to `false`" }, - "issuedAtDate": { + "expirationDate": { "type": "boolean", - "description": "policy to override the issuedAtDate (iat) timestamp check" + "description": "policy to skip the expirationDate (exp) timestamp check when set to `false`" }, - "expirationDate": { + "audience": { + "type": "boolean", + "description": "policy to skip the audience check when set to `false`" + }, + "credentialStatus": { "type": "boolean", - "description": "policy to override the expirationDate (exp) timestamp check" + "description": "policy to skip the revocation check (credentialStatus) when set to `false`" } }, + "required": [ + "credentialStatus" + ], "additionalProperties": { "description": "Other options can be specified for verification. They will be forwarded to the lower level modules that perform the checks" }, @@ -484,6 +451,50 @@ } }, "description": "An error object, which can contain a code." + }, + "IVerifyPresentationArgs": { + "type": "object", + "properties": { + "presentation": { + "$ref": "#/components/schemas/W3CVerifiablePresentation", + "description": "The Verifiable Presentation object according to the\n {@link https://www.w3.org/TR/vc-data-model/#presentations | canonical model } or the JWT representation.\n\nThe signer of the Presentation is verified based on the `holder` property of the `presentation` or the `iss` property of the JWT payload respectively" + }, + "challenge": { + "type": "string", + "description": "Optional (only for JWT) string challenge parameter to verify the verifiable presentation against" + }, + "domain": { + "type": "string", + "description": "Optional (only for JWT) string domain parameter to verify the verifiable presentation against" + }, + "fetchRemoteContexts": { + "type": "boolean", + "description": "When dealing with JSON-LD you also MUST provide the proper contexts. Set this to `true` ONLY if you want the '@context' URLs to be fetched in case they are not pre-loaded. The context definitions SHOULD rather be provided at startup instead of being fetched.", + "default": false + }, + "policies": { + "$ref": "#/components/schemas/VerificationPolicies", + "description": "Overrides specific aspects of credential verification, where possible." + } + }, + "required": [ + "presentation" + ], + "additionalProperties": { + "description": "Other options can be specified for verification. They will be forwarded to the lower level modules. that performt the checks" + }, + "description": "Encapsulates the parameters required to verify a\n {@link https://www.w3.org/TR/vc-data-model/#presentations | W3C Verifiable Presentation }" + }, + "W3CVerifiablePresentation": { + "anyOf": [ + { + "$ref": "#/components/schemas/VerifiablePresentation" + }, + { + "$ref": "#/components/schemas/CompactJWT" + } + ], + "description": "Represents a signed Verifiable Presentation (includes proof) in either JSON or compact JWT format. See {@link https://www.w3.org/TR/vc-data-model/#credentials | VC data model }" } }, "methods": { @@ -511,7 +522,7 @@ "$ref": "#/components/schemas/IVerifyCredentialArgs" }, "returnType": { - "type": "boolean" + "$ref": "#/components/schemas/IVerifyResult" } }, "verifyPresentation": { diff --git a/packages/credential-w3c/src/action-handler.ts b/packages/credential-w3c/src/action-handler.ts index 2d1f7593ed..8f74722f6c 100644 --- a/packages/credential-w3c/src/action-handler.ts +++ b/packages/credential-w3c/src/action-handler.ts @@ -39,7 +39,7 @@ import Debug from 'debug' import { Resolvable } from 'did-resolver' import { schema } from './' -const enum CredentialType { +const enum DocumentFormat { JWT, JSONLD, EIP712, @@ -185,6 +185,11 @@ export interface IVerifyCredentialArgs { */ fetchRemoteContexts?: boolean + /** + * Overrides specific aspects of credential verification, where possible. + */ + policies?: VerificationPolicies + /** * Other options can be specified for verification. * They will be forwarded to the lower level modules. that performt the checks @@ -228,17 +233,15 @@ export interface IVerifyPresentationArgs { */ fetchRemoteContexts?: boolean - /** - * Verification Policies for the verifiable presentation - * These will also be forwarded to the lower level module + * Overrides specific aspects of credential verification, where possible. */ - policies?: VerifyPresentationPolicies + policies?: VerificationPolicies /** * Other options can be specified for verification. * They will be forwarded to the lower level modules. that performt the checks - */ + */ [x: string]: any } @@ -248,31 +251,36 @@ export interface IVerifyPresentationArgs { * * @beta */ -export interface VerifyPresentationPolicies { +export interface VerificationPolicies { /** - * policy to over the now (current time) during the verification check + * policy to over the now (current time) during the verification check (UNIX time in seconds) */ now?: number /** - * policy to override the issuanceDate (nbf) timestamp check + * policy to skip the issuanceDate (nbf) timestamp check when set to `false` */ issuanceDate?: boolean /** - * policy to override the issuedAtDate (iat) timestamp check + * policy to skip the expirationDate (exp) timestamp check when set to `false` */ - issuedAtDate?: boolean + expirationDate?: boolean /** - * policy to override the expirationDate (exp) timestamp check + * policy to skip the audience check when set to `false` */ - expirationDate?: boolean + audience?: boolean + + /** + * policy to skip the revocation check (credentialStatus) when set to `false` + */ + credentialStatus: boolean /** * Other options can be specified for verification. * They will be forwarded to the lower level modules that perform the checks - */ + */ [x: string]: any } @@ -332,11 +340,12 @@ export interface ICredentialIssuer extends IPluginMethodMap { * @param args - Arguments necessary to verify a VerifiableCredential * @param context - This reserved param is automatically added and handled by the framework, *do not override* * - * @returns - a promise that resolves to the boolean true on successful verification or rejects on error + * @returns - a promise that resolves to an object containing a `verified` boolean property and an optional `error` + * for details * * @remarks Please see {@link https://www.w3.org/TR/vc-data-model/#credentials | Verifiable Credential data model} */ - verifyCredential(args: IVerifyCredentialArgs, context: IContext): Promise + verifyCredential(args: IVerifyCredentialArgs, context: IContext): Promise /** * Verifies a Verifiable Presentation JWT or LDS Format. @@ -344,7 +353,8 @@ export interface ICredentialIssuer extends IPluginMethodMap { * @param args - Arguments necessary to verify a VerifiableCredential * @param context - This reserved param is automatically added and handled by the framework, *do not override* * - * @returns - a promise that resolves to the boolean true on successful verification or rejects on error + * @returns - a promise that resolves to an object containing a `verified` boolean property and an optional `error` + * for details * * @remarks Please see {@link https://www.w3.org/TR/vc-data-model/#presentations | Verifiable Credential data model} */ @@ -552,59 +562,101 @@ export class CredentialIssuer implements IAgentPlugin { } /** {@inheritdoc ICredentialIssuer.verifyCredential} */ - async verifyCredential(args: IVerifyCredentialArgs, context: IContext): Promise { + async verifyCredential(args: IVerifyCredentialArgs, context: IContext): Promise { const credential = args.credential let verifiedCredential: VerifiableCredential + let verificationResult: IVerifyResult = { verified: false } - const type: CredentialType = detectCredentialType(credential) - if (type == CredentialType.JWT) { + const type: DocumentFormat = detectDocumentType(credential) + if (type == DocumentFormat.JWT) { let jwt: string = typeof credential === 'string' ? credential : credential.proof.jwt const resolver = { resolve: (didUrl: string) => context.agent.resolveDid({ didUrl }) } as Resolvable try { - const verification = await verifyCredentialJWT(jwt, resolver) - verifiedCredential = verification.verifiableCredential + verificationResult = await verifyCredentialJWT(jwt, resolver, { + policies: { + nbf: args.policies?.issuanceDate, + iat: args.policies?.issuanceDate, + exp: args.policies?.expirationDate, + aud: args.policies?.audience, + ...args.policies, + }, + }) + verifiedCredential = verificationResult.verifiableCredential } catch (e: any) { - //TODO: return a more detailed reason for failure - return false + let { message, errorCode } = e + return { + verified: false, + error: { + message, + errorCode: errorCode ? errorCode : message.split(':')[0], + }, + } } - } else if (type == CredentialType.EIP712) { + } else if (type == DocumentFormat.EIP712) { if (typeof context.agent.verifyCredentialEIP712 !== 'function') { throw new Error( 'invalid_configuration: your agent does not seem to have ICredentialIssuerEIP712 plugin installed', ) } - if (!(await context.agent.verifyCredentialEIP712(args))) { - return false + try { + const result = await context.agent.verifyCredentialEIP712(args) + if (result) { + verificationResult = { + verified: true, + } + } else { + verificationResult = { + verified: false, + error: { + message: "invalid_signature: The signature does not match any of the issuer signing keys", + errorCode: "invalid_signature" + } + } + } + verifiedCredential = credential + } catch (e: any) { + const { message, errorCode } = e + return { + verified: false, + error: { + message, + errorCode: errorCode ? errorCode : e.message.split(':')[0], + }, + } } - - verifiedCredential = credential - } else if (type == CredentialType.JSONLD) { + } else if (type == DocumentFormat.JSONLD) { if (typeof context.agent.verifyCredentialLD !== 'function') { throw new Error( 'invalid_configuration: your agent does not seem to have ICredentialIssuerLD plugin installed', ) } - if (!(await context.agent.verifyCredentialLD(args))) return false - + verificationResult = await context.agent.verifyCredentialLD(args) verifiedCredential = credential } else { throw new Error('Unknown credential type.') } - if (await isRevoked(verifiedCredential, context)) { - return false + if (args.policies?.credentialStatus !== false && (await isRevoked(verifiedCredential, context))) { + verificationResult = { + verified: false, + error: { + message: 'revoked: The credential was revoked by the issuer', + errorCode: 'revoked', + }, + } } - return true + return verificationResult } /** {@inheritdoc ICredentialIssuer.verifyPresentation} */ async verifyPresentation(args: IVerifyPresentationArgs, context: IContext): Promise { const presentation = args.presentation - if (typeof presentation === 'string' || (presentation)?.proof?.jwt) { + const type: DocumentFormat = detectDocumentType(presentation) + if (type === DocumentFormat.JWT) { // JWT let jwt: string if (typeof presentation === 'string') { @@ -635,17 +687,53 @@ export class CredentialIssuer implements IAgentPlugin { audience, policies: { nbf: args.policies?.issuanceDate, - iat: args.policies?.issuedAtDate, - now: args.policies?.now, - exp: args.policies?.expirationDate - } + iat: args.policies?.issuanceDate, + exp: args.policies?.expirationDate, + ...args.policies, + }, }) - return { verified: true } + return verification } catch (e: any) { - - // Need this logic for the errorCode because ErrorCodes are not being exported from did-jwt - // Uncase the code is not present the ErrorCode property will be undefined - return { verified: false, error: { message: e.message, errorCode: e.message.split(':')[0] } } + let { message, errorCode } = e + return { + verified: false, + error: { + message, + errorCode: errorCode ? errorCode : message.split(':')[0], + }, + } + } + } else if (type === DocumentFormat.EIP712) { + // JSON-LD + if (typeof context.agent.verifyPresentationEIP712 !== 'function') { + throw new Error( + 'invalid_configuration: your agent does not seem to have ICredentialIssuerEIP712 plugin installed', + ) + } + try { + const result = await context.agent.verifyPresentationEIP712(args) + if (result) { + return { + verified: true, + } + } else { + return { + verified: false, + error: { + message: "invalid_signature: The signature does not match any of the issuer signing keys", + errorCode: "invalid_signature" + } + } + } + } catch (e: any) { + const { message, errorCode } = e + return { + verified: false, + error: { + message, + errorCode: errorCode ? errorCode : e.message.split(':')[0], + }, + } } } else { // JSON-LD @@ -672,21 +760,22 @@ function wrapSigner( } } -function detectCredentialType(credential: W3CVerifiableCredential): CredentialType { - if (typeof credential === 'string' || (credential)?.proof?.jwt) - return CredentialType.JWT - if ((credential)?.proof?.type === 'EthereumEip712Signature2021') - return CredentialType.EIP712 - return CredentialType.JSONLD +function detectDocumentType(document: W3CVerifiableCredential | W3CVerifiablePresentation): DocumentFormat { + if (typeof document === 'string' || (document)?.proof?.jwt) return DocumentFormat.JWT + if ((document)?.proof?.type === 'EthereumEip712Signature2021') + return DocumentFormat.EIP712 + return DocumentFormat.JSONLD } -async function isRevoked(credential: VerifiableCredential, context: IAgentContext): Promise { +async function isRevoked(credential: VerifiableCredential, context: IContext): Promise { if (!credential.credentialStatus) return false if (typeof context.agent.checkCredentialStatus === 'function') { const status = await context.agent.checkCredentialStatus({ credential }) - return status?.revoked == true + return status?.revoked == true || status?.verified === false } - throw new Error(`invalid_config: The credential status can't be verified by the agent`) + throw new Error( + `invalid_config: The credential status can't be verified because there is no ICredentialStatusVerifier plugin installed.`, + ) } diff --git a/packages/credential-w3c/src/message-handler.ts b/packages/credential-w3c/src/message-handler.ts index c553359186..1afd4028ad 100644 --- a/packages/credential-w3c/src/message-handler.ts +++ b/packages/credential-w3c/src/message-handler.ts @@ -6,7 +6,9 @@ import { normalizePresentation, validateJwtCredentialPayload, validateJwtPresentationPayload, + VC_ERROR, } from 'did-jwt-vc' +import { JWT_ERROR } from 'did-jwt' import { ICredentialIssuer } from './action-handler' import { v4 as uuidv4 } from 'uuid' import Debug from 'debug' @@ -33,6 +35,16 @@ export const MessageTypes = { */ export type IContext = IAgentContext +const validityErrors: string[] = [ + JWT_ERROR.INVALID_JWT, + JWT_ERROR.INVALID_AUDIENCE, + JWT_ERROR.INVALID_SIGNATURE, + JWT_ERROR.NO_SUITABLE_KEYS, + VC_ERROR.SCHEMA_ERROR, + VC_ERROR.FORMAT_ERROR, + VC_ERROR.AUTH_ERROR, +] + /** * An implementation of the {@link @veramo/message-handler#AbstractMessageHandler}. * @@ -105,20 +117,23 @@ export class W3cMessageHandler extends AbstractMessageHandler { // verify credential const credential = message.data as VerifiableCredential - // throws on error. - await context.agent.verifyCredential({ credential }) - message.id = computeEntryHash(message.raw || message.id || uuidv4()) - message.type = MessageTypes.vc - message.from = extractIssuer(credential) - message.to = credential.credentialSubject.id - - if (credential.tag) { - message.threadId = credential.tag - } + const result = await context.agent.verifyCredential({ credential }) + if (result.verified) { + message.id = computeEntryHash(message.raw || message.id || uuidv4()) + message.type = MessageTypes.vc + message.from = extractIssuer(credential) + message.to = credential.credentialSubject.id - message.createdAt = credential.issuanceDate - message.credentials = [credential] - return message + if (credential.tag) { + message.threadId = credential.tag + } + + message.createdAt = credential.issuanceDate + message.credentials = [credential] + return message + } else { + throw new Error(result.error?.message) + } } if (message.type === MessageTypes.vp && message.data) { @@ -126,26 +141,29 @@ export class W3cMessageHandler extends AbstractMessageHandler { const presentation = message.data as VerifiablePresentation // throws on error. - await context.agent.verifyPresentation({ + const result = await context.agent.verifyPresentation({ presentation, // FIXME: HARDCODED CHALLENGE VERIFICATION FOR NOW challenge: 'VERAMO', domain: 'VERAMO', }) + if (result.verified) { + message.id = computeEntryHash(message.raw || message.id || uuidv4()) + message.type = MessageTypes.vp + message.from = presentation.holder + // message.to = presentation.verifier?.[0] - message.id = computeEntryHash(message.raw || message.id || uuidv4()) - message.type = MessageTypes.vp - message.from = presentation.holder - // message.to = presentation.verifier?.[0] + if (presentation.tag) { + message.threadId = presentation.tag + } - if (presentation.tag) { - message.threadId = presentation.tag + // message.createdAt = presentation.issuanceDate + message.presentations = [presentation] + message.credentials = asArray(presentation.verifiableCredential).map(decodeCredentialToObject) + return message + } else { + throw new Error(result.error?.message) } - - // message.createdAt = presentation.issuanceDate - message.presentations = [presentation] - message.credentials = asArray(presentation.verifiableCredential).map(decodeCredentialToObject) - return message } return super.handle(message, context) diff --git a/packages/did-comm/package.json b/packages/did-comm/package.json index 95da054e45..3de9b5b888 100644 --- a/packages/did-comm/package.json +++ b/packages/did-comm/package.json @@ -21,7 +21,7 @@ "@veramo/utils": "^3.1.4", "cross-fetch": "^3.1.4", "debug": "^4.3.3", - "did-jwt": "^6.3.0", + "did-jwt": "^6.5.0", "did-resolver": "^4.0.0", "uint8arrays": "^3.0.0", "uuid": "^8.3.0" diff --git a/packages/did-jwt/package.json b/packages/did-jwt/package.json index a07bdbee0f..08c750f362 100644 --- a/packages/did-jwt/package.json +++ b/packages/did-jwt/package.json @@ -12,7 +12,7 @@ "@veramo/core": "^3.1.4", "@veramo/message-handler": "^3.1.4", "debug": "^4.3.3", - "did-jwt": "^6.3.0", + "did-jwt": "^6.5.0", "did-resolver": "^4.0.0" }, "devDependencies": { diff --git a/packages/did-jwt/src/message-handler.ts b/packages/did-jwt/src/message-handler.ts index f020803b17..00a9aed380 100644 --- a/packages/did-jwt/src/message-handler.ts +++ b/packages/did-jwt/src/message-handler.ts @@ -3,6 +3,7 @@ import { AbstractMessageHandler, Message } from '@veramo/message-handler' import { verifyJWT, decodeJWT } from 'did-jwt' import Debug from 'debug' import { Resolvable } from 'did-resolver' + const debug = Debug('veramo:did-jwt:message-handler') export type IContext = IAgentContext @@ -18,10 +19,14 @@ export class JwtMessageHandler extends AbstractMessageHandler { const decoded = decodeJWT(message.raw) const audience = Array.isArray(decoded.payload.aud) ? decoded.payload.aud[0] : decoded.payload.aud const resolver = { resolve: (didUrl: string) => context.agent.resolveDid({ didUrl }) } as Resolvable - const verified = await verifyJWT(message.raw, { resolver, audience }) - debug('Message.raw is a valid JWT') - message.addMetaData({ type: decoded.header.typ || 'JWT', value: decoded.header.alg }) - message.data = verified.payload + const result = await verifyJWT(message.raw, { resolver, audience }) + if (result.verified) { + debug('Message.raw is a valid JWT') + message.addMetaData({ type: decoded.header.typ || 'JWT', value: decoded.header.alg }) + message.data = result.payload + } else { + debug(result) + } } catch (e: any) { debug(e.message) } diff --git a/packages/did-provider-ethr/package.json b/packages/did-provider-ethr/package.json index bf6863d243..567bad0e25 100644 --- a/packages/did-provider-ethr/package.json +++ b/packages/did-provider-ethr/package.json @@ -1,6 +1,6 @@ { "name": "@veramo/did-provider-ethr", - "description": "Veramo ehtr-did based identity controller plugin.", + "description": "Veramo ethr-did based identity controller plugin.", "version": "3.1.4", "main": "build/index.js", "types": "build/index.d.ts", diff --git a/packages/key-manager/package.json b/packages/key-manager/package.json index bf032a3c91..afd745656a 100644 --- a/packages/key-manager/package.json +++ b/packages/key-manager/package.json @@ -14,12 +14,12 @@ "@ethersproject/transactions": "^5.6.2", "@stablelib/ed25519": "^1.0.2", "@veramo/core": "^3.1.4", - "did-jwt": "^6.3.0", + "did-jwt": "^6.5.0", "uint8arrays": "^3.0.0", "uuid": "^8.3.2" }, "devDependencies": { - "@ethersproject/abstract-signer": "^5.6.2", + "@ethersproject/abstract-signer": "5.6.2", "typescript": "4.7.3" }, "files": [ diff --git a/packages/kms-local/package.json b/packages/kms-local/package.json index 79ec08fbb1..dcf0e3dfcf 100644 --- a/packages/kms-local/package.json +++ b/packages/kms-local/package.json @@ -22,7 +22,7 @@ "@veramo/key-manager": "^3.1.4", "base-58": "^0.0.1", "debug": "^4.3.3", - "did-jwt": "^6.3.0", + "did-jwt": "^6.5.0", "uint8arrays": "^3.0.0" }, "devDependencies": { diff --git a/packages/selective-disclosure/package.json b/packages/selective-disclosure/package.json index f44a6a3541..25c4611b28 100644 --- a/packages/selective-disclosure/package.json +++ b/packages/selective-disclosure/package.json @@ -19,7 +19,7 @@ "@veramo/did-jwt": "^3.1.4", "@veramo/message-handler": "^3.1.4", "debug": "^4.3.3", - "did-jwt": "^6.3.0", + "did-jwt": "^6.5.0", "uuid": "^8.3.0" }, "devDependencies": { diff --git a/packages/utils/package.json b/packages/utils/package.json index c692348c16..a79e062921 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -15,8 +15,8 @@ "blakejs": "^1.1.1", "cross-fetch": "^3.1.4", "debug": "^4.3.3", - "did-jwt": "^6.3.0", - "did-jwt-vc": "^2.1.14", + "did-jwt": "^6.5.0", + "did-jwt-vc": "3.0.1", "did-resolver": "^4.0.0", "uint8arrays": "^3.0.0", "uuid": "^8.3.0" diff --git a/yarn.lock b/yarn.lock index 848b5688f3..3c14d58dce 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7403,7 +7403,7 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -credential-status@^2.0.5: +credential-status@2.0.5, credential-status@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/credential-status/-/credential-status-2.0.5.tgz#59e34d30b85664160dd77a4357f1a1237cb7b2bc" integrity sha512-hh0pOcRidROn4MC1wF3vNURhPEMSzm3RcpFIl5PFVj5HWgCaZy16nXmrOl5cmr50Jhp2WV48cWbNMxh4OFWU+w== @@ -7958,15 +7958,15 @@ dezalgo@^1.0.0: asap "^2.0.0" wrappy "1" -did-jwt-vc@^2.1.14: - version "2.1.14" - resolved "https://registry.yarnpkg.com/did-jwt-vc/-/did-jwt-vc-2.1.14.tgz#0668354d986da7577b830e866bec961584df3c01" - integrity sha512-z3y1sVXi4jdgomK6ZAtAjfkWiRUeMHFfQQ+RMozWdpOW8ECvQlFJE95NmF3E6fpLEyafPthEBAsb1hm4uNcY2g== +did-jwt-vc@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/did-jwt-vc/-/did-jwt-vc-3.0.1.tgz#d390957ac54fbc6504cba5dbad6df410c54136f1" + integrity sha512-M4GvWC7WFXjyPXXVdxD+IP8+KUbyizxPFB2z8fErnYQfdQzWuPqz4PM4MkgI3I4V66lNKfn6bgUivXVTuP8i2Q== dependencies: - did-jwt "^6.2.2" + did-jwt "^6.5.0" did-resolver "^4.0.0" -did-jwt@^6.2.2, did-jwt@^6.3.0: +did-jwt@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/did-jwt/-/did-jwt-6.3.0.tgz#6c7380a69fff97f95101ce03519fd34c0ee43594" integrity sha512-kvwCDY6KZJZn9/LK+X4Co+X1brnZWr6fnP1NRVReTgSPFyA+20oZ+VCsmSnzzYUoPkQ/Pl54uOMlmRw69z5zBg== @@ -7984,7 +7984,25 @@ did-jwt@^6.2.2, did-jwt@^6.3.0: multiformats "^9.6.5" uint8arrays "^3.0.0" -did-resolver@^4.0.0: +did-jwt@^6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/did-jwt/-/did-jwt-6.5.0.tgz#0179ed25db32c111a667563c0d7b54e5d6ecb939" + integrity sha512-yfdqk2N6+161Yeay4HMC5daic/HRIsc+W1r7JQlNtL14fmQyaPgJxnxpXdc7Qmwd+pMlfpi1oOEtraExDE6MzQ== + dependencies: + "@stablelib/ed25519" "^1.0.2" + "@stablelib/random" "^1.0.1" + "@stablelib/sha256" "^1.0.1" + "@stablelib/x25519" "^1.0.2" + "@stablelib/xchacha20poly1305" "^1.0.1" + bech32 "^2.0.0" + canonicalize "^1.0.8" + did-resolver "^4.0.0" + elliptic "^6.5.4" + js-sha3 "^0.8.0" + multiformats "^9.6.5" + uint8arrays "^3.0.0" + +did-resolver@4.0.0, did-resolver@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/did-resolver/-/did-resolver-4.0.0.tgz#fc8f657b4cd7f44c2921051fb046599fbe7d4b31" integrity sha512-/roxrDr9EnAmLs+s9T+8+gcpilMo+IkeytcsGO7dcxvTmVJ+0Rt60HtV8o0UXHhGBo0Q+paMH/0ffXz1rqGFYg==