@credo-ts/core
Version:
<p align="center"> <br /> <img alt="Credo Logo" src="https://github.com/openwallet-foundation/credo-ts/blob/c7886cb8377ceb8ee4efe8d264211e561a75072d/images/credo-logo.png" height="250px" /> </p> <h1 align="center"><b>Credo - Core</b></h1
1 lines • 27 kB
Source Map (JSON)
{"version":3,"file":"W3cJsonLdCredentialService.mjs","names":["vc","jsonld"],"sources":["../../../../src/modules/vc/linked-data-proofs/W3cJsonLdCredentialService.ts"],"sourcesContent":["import type { AgentContext } from '../../../agent/context'\nimport { TrustedIssuerContext } from '../../../agent/TrustedIssuerContext'\nimport type { TrustedIssuerDid } from '../../../agent/TrustedIssuersForVerification'\nimport { createKmsKeyPairClass } from '../../../crypto/KmsKeyPair'\nimport { CredoError, RecordNotFoundError } from '../../../error'\nimport { injectable } from '../../../plugins'\nimport type { SingleOrArray } from '../../../types'\nimport { asArray, JsonTransformer } from '../../../utils'\nimport { type DidPurpose, DidsApi, parseDid } from '../../dids'\nimport { ANONCREDS_W3C_CREDENTIAL_CRYPTOSUITE } from '../anoncreds-w3c-credential'\nimport { JsonLdModuleConfig } from '../jsonld'\nimport jsonld from '../jsonld/jsonld'\nimport type { SingleValidationResult, W3cVerifyCredentialResult, W3cVerifyPresentationResult } from '../models'\nimport type { W3cJsonCredential } from '../models/credential/W3cJsonCredential'\nimport { validateCredentialSubjectAuthentication, w3cDate } from '../util'\nimport type {\n W3cJsonLdSignCredentialOptions,\n W3cJsonLdSignPresentationOptions,\n W3cJsonLdVerifyCredentialOptions,\n W3cJsonLdVerifyPresentationOptions,\n} from '../W3cCredentialServiceOptions'\nimport vc from './adapters/vc-adapter'\nimport { W3cJsonLdVerifiableCredential } from './models/W3cJsonLdVerifiableCredential'\nimport { W3cJsonLdVerifiablePresentation } from './models/W3cJsonLdVerifiablePresentation'\nimport { assertOnlyW3cJsonLdVerifiableCredentials } from './proof-ops/jsonldUtil'\nimport { SignatureSuiteRegistry } from './SignatureSuiteRegistry'\nimport { W3cJsonLdCredentialSigningNotSupportedError } from './W3cJsonLdCredentialSigningNotSupportedError'\n\n/**\n * Supports signing and verification of credentials according to the [Verifiable Credential Data Model](https://www.w3.org/TR/vc-data-model)\n * using [Linked Data Proofs](https://www.w3.org/TR/vc-data-model/#proofs).\n */\n@injectable()\nexport class W3cJsonLdCredentialService {\n private signatureSuiteRegistry: SignatureSuiteRegistry\n private jsonLdModuleConfig: JsonLdModuleConfig\n\n public constructor(signatureSuiteRegistry: SignatureSuiteRegistry, jsonLdModuleConfig: JsonLdModuleConfig) {\n this.signatureSuiteRegistry = signatureSuiteRegistry\n this.jsonLdModuleConfig = jsonLdModuleConfig\n }\n\n /**\n * Signs a credential\n */\n public async signCredential(\n agentContext: AgentContext,\n options: W3cJsonLdSignCredentialOptions\n ): Promise<W3cJsonLdVerifiableCredential> {\n const { suite } = await this.prepareSigningSuite(agentContext, {\n proofType: options.proofType,\n verificationMethodId: options.verificationMethod,\n allowedPurposes: options.proofPurpose?.term ? [options.proofPurpose.term] : ['assertionMethod'],\n date: options.created ?? w3cDate(),\n controller: options.credential.issuerId,\n })\n\n try {\n const result = await vc.issue({\n credential: JsonTransformer.toJSON(options.credential),\n suite: suite,\n purpose: options.proofPurpose,\n documentLoader: this.jsonLdModuleConfig.documentLoader(agentContext),\n })\n\n return JsonTransformer.fromJSON(result, W3cJsonLdVerifiableCredential)\n } catch (error) {\n throw new CredoError(`Error issuing W3C JSON-LD VC. ${error.message}`, {\n cause: error,\n })\n }\n }\n\n /**\n * Validate that the agent can prepare to sign a credential with the given proof type and verification method.\n */\n public async assertCanSignCredential(\n agentContext: AgentContext,\n options: Pick<W3cJsonLdSignCredentialOptions, 'proofType' | 'verificationMethod'> & { controller?: string }\n ): Promise<void> {\n await this.prepareSigningSuite(agentContext, {\n proofType: options.proofType,\n verificationMethodId: options.verificationMethod,\n allowedPurposes: ['assertionMethod'],\n controller: options.controller,\n })\n }\n\n /**\n * Verifies the signature(s) of a credential\n *\n * @param credential the credential to be verified\n * @returns the verification result\n */\n public async verifyCredential(\n agentContext: AgentContext,\n options: W3cJsonLdVerifyCredentialOptions\n ): Promise<W3cVerifyCredentialResult> {\n try {\n this.assertNoAnonCredsW3cCredentialProof(options.credential.proof)\n\n const verifyCredentialStatus = options.verifyCredentialStatus ?? true\n\n await this.ensureCredentialIssuerTrusted(agentContext, options.credential, options.trustedIssuers)\n\n const suites = this.getSignatureSuitesForCredential(agentContext, options.credential)\n\n const verifyOptions: Record<string, unknown> = {\n credential: JsonTransformer.toJSON(options.credential),\n suite: suites,\n documentLoader: this.jsonLdModuleConfig.documentLoader(agentContext),\n checkStatus: ({ credential }: { credential: W3cJsonCredential }) => {\n // Only throw error if credentialStatus is present\n if (verifyCredentialStatus && 'credentialStatus' in credential) {\n throw new CredoError('Verifying credential status for JSON-LD credentials is currently not supported')\n }\n return {\n verified: true,\n }\n },\n }\n\n // this is a hack because vcjs throws if purpose is passed as undefined or null\n if (options.proofPurpose) {\n verifyOptions.purpose = options.proofPurpose\n }\n\n const result = await vc.verifyCredential(verifyOptions)\n\n const { verified: isValid, ...remainingResult } = result\n\n if (!isValid) {\n agentContext.config.logger.debug(`Credential verification failed: ${result.error?.message}`, {\n stack: result.error?.stack,\n })\n }\n\n // We map the result to our own result type to make it easier to work with\n // however, for now we just add a single vcJs validation result as we don't\n // have access to the internal validation results of vc-js\n return {\n isValid,\n validations: {\n vcJs: {\n isValid,\n ...remainingResult,\n },\n },\n error: result.error,\n }\n } catch (error) {\n return {\n isValid: false,\n validations: {},\n error,\n }\n }\n }\n\n /**\n * Signs a presentation including the credentials it includes\n *\n * @param presentation the presentation to be signed\n * @returns the signed presentation\n */\n public async signPresentation(\n agentContext: AgentContext,\n options: W3cJsonLdSignPresentationOptions\n ): Promise<W3cJsonLdVerifiablePresentation> {\n const { suite } = await this.prepareSigningSuite(agentContext, {\n proofType: options.proofType,\n verificationMethodId: options.verificationMethod,\n allowedPurposes: options.proofPurpose?.term ? [options.proofPurpose.term] : ['authentication'],\n date: new Date().toISOString(),\n })\n\n const signOptions: Record<string, unknown> = {\n presentation: JsonTransformer.toJSON(options.presentation),\n suite: suite,\n challenge: options.challenge,\n domain: options.domain,\n documentLoader: this.jsonLdModuleConfig.documentLoader(agentContext),\n }\n\n // this is a hack because vcjs throws if purpose is passed as undefined or null\n if (options.proofPurpose) {\n signOptions.purpose = options.proofPurpose\n }\n\n const result = await vc.signPresentation(signOptions)\n\n return JsonTransformer.fromJSON(result, W3cJsonLdVerifiablePresentation)\n }\n\n /**\n * Verifies a presentation including the credentials it includes\n *\n * @param presentation the presentation to be verified\n * @returns the verification result\n */\n public async verifyPresentation(\n agentContext: AgentContext,\n options: W3cJsonLdVerifyPresentationOptions\n ): Promise<W3cVerifyPresentationResult> {\n try {\n this.assertNoAnonCredsW3cCredentialProof(options.presentation.proof)\n\n // create keyPair\n const WalletKeyPair = createKmsKeyPairClass(agentContext)\n\n let proofs = options.presentation.proof\n\n if (!Array.isArray(proofs)) {\n proofs = [proofs]\n }\n if (options.purpose) {\n proofs = proofs.filter((proof) => proof.proofPurpose === options.purpose.term)\n }\n\n const presentationSuites = proofs.map((proof) => {\n const SuiteClass = this.signatureSuiteRegistry.getByProofType(proof.type).suiteClass\n return new SuiteClass({\n LDKeyClass: WalletKeyPair,\n proof: {\n verificationMethod: proof.verificationMethod,\n },\n date: proof.created,\n useNativeCanonize: false,\n })\n })\n\n const credentials = asArray(options.presentation.verifiableCredential)\n assertOnlyW3cJsonLdVerifiableCredentials(credentials)\n\n for (const credential of credentials) {\n this.assertNoAnonCredsW3cCredentialProof(credential.proof)\n await this.ensureCredentialIssuerTrusted(agentContext, credential, options.trustedIssuers)\n }\n\n const credentialSuites = credentials.map((credential) =>\n this.getSignatureSuitesForCredential(agentContext, credential)\n )\n const allSuites = presentationSuites.concat(...credentialSuites)\n\n const verifyOptions: Record<string, unknown> = {\n presentation: JsonTransformer.toJSON(options.presentation),\n suite: allSuites,\n challenge: options.challenge,\n domain: options.domain,\n documentLoader: this.jsonLdModuleConfig.documentLoader(agentContext),\n }\n\n // this is a hack because vcjs throws if purpose is passed as undefined or null\n if (options.purpose) {\n verifyOptions.presentationPurpose = options.purpose\n }\n\n const result = await vc.verify(verifyOptions)\n\n const { verified: isValid, ...remainingResult } = result\n\n // The vc-js / jsonld-signatures libraries verify the presentation proof and each embedded\n // credential's issuer proof, but do NOT bind the presentation signer (holder) to the\n // credentialSubject of the embedded credentials. Without this check an attacker could wrap\n // someone else's credential (a data object, not a secret) in a presentation signed with their\n // own key and have it accepted. Enforce the binding here, mirroring the jwt_vp and sd-jwt paths\n // (see validateCredentialSubjectAuthentication).\n //\n // The holder identity is derived from the verificationMethod of the presentation's\n // authentication proof(s), which vc-js has already cryptographically verified and authorized\n // for the authentication purpose. validateCredentialSubjectAuthentication normalizes the DID\n // URL to its bare DID before comparison; for the DID methods used with linked-data proofs the\n // verificationMethod's DID equals its controller.\n const holderProofPurpose = options.purpose?.term ?? 'authentication'\n const holderVerificationMethods = asArray(options.presentation.proof)\n .filter((proof) => proof.proofPurpose === holderProofPurpose)\n .map((proof) => proof.verificationMethod)\n\n // Surfaced per credential under `credentials[]` to mirror the jwt_vp result shape. The\n // library-level signature/status validations remain lumped in `vcJs`, so each entry here\n // only carries the credentialSubjectAuthentication check.\n const credentialValidations = credentials.map((credential) => {\n const credentialSubjectIds = credential.credentialSubjectIds\n\n // A credential without subject identifiers is treated as a bearer credential,\n // so there is no subject to authenticate.\n const isAuthenticated =\n credentialSubjectIds.length === 0 ||\n holderVerificationMethods.some(\n (verificationMethod) =>\n validateCredentialSubjectAuthentication(credentialSubjectIds, verificationMethod).isValid\n )\n\n const credentialSubjectAuthentication: SingleValidationResult = isAuthenticated\n ? { isValid: true }\n : {\n isValid: false,\n error: new CredoError(\n 'Presentation does not authenticate the credentialSubject of one or more included credentials'\n ),\n }\n\n return {\n isValid: credentialSubjectAuthentication.isValid,\n validations: { credentialSubjectAuthentication },\n }\n })\n\n // We map the result to our own result type to make it easier to work with. The library\n // validations are lumped into a single vcJs result as we don't have access to the internal\n // validation results of vc-js; the credentialSubject authentication check that Credo performs\n // on top is surfaced per credential under `credentials`.\n return {\n isValid: isValid && credentialValidations.every((credential) => credential.isValid),\n validations: {\n vcJs: {\n isValid,\n ...remainingResult,\n },\n credentials: credentialValidations,\n },\n error:\n result.error ??\n credentialValidations.find((credential) => !credential.isValid)?.validations.credentialSubjectAuthentication\n .error,\n }\n } catch (error) {\n return {\n isValid: false,\n validations: {},\n error,\n }\n }\n }\n\n public getVerificationMethodTypesByProofType(proofType: string): string[] {\n return this.getSigningSuiteInfo(proofType).verificationMethodTypes\n }\n\n public async getExpandedTypesForCredential(agentContext: AgentContext, credential: W3cJsonLdVerifiableCredential) {\n // Get the expanded types\n const expandedTypes: SingleOrArray<string> = (\n await jsonld.expand(JsonTransformer.toJSON(credential), {\n documentLoader: this.jsonLdModuleConfig.documentLoader(agentContext),\n })\n )[0]['@type']\n\n return asArray(expandedTypes)\n }\n\n private async ensureCredentialIssuerTrusted(\n agentContext: AgentContext,\n credential: W3cJsonLdVerifiableCredential,\n trustedIssuers?: TrustedIssuerDid[]\n ): Promise<void> {\n const issuerId = credential.issuerId\n\n // Only enforced for did-based issuers\n if (!issuerId.startsWith('did:')) return\n\n const issuerDid = parseDid(issuerId).did\n\n for (const proof of asArray(credential.proof)) {\n const verificationMethod = proof.verificationMethod\n if (!verificationMethod.startsWith('did:') || parseDid(verificationMethod).did !== issuerDid) {\n throw new CredoError(\n `The proof verification method '${verificationMethod}' does not match the credential issuer did '${issuerDid}'.`\n )\n }\n\n await TrustedIssuerContext.ensureTrustedSigner(\n agentContext,\n {\n signer: { method: 'did', didUrl: verificationMethod },\n verification: { type: 'credential', credential },\n },\n trustedIssuers\n )\n }\n }\n\n private getSigningSuiteInfo(proofType: string) {\n if (!this.signatureSuiteRegistry.supportedProofTypes.includes(proofType)) {\n throw new W3cJsonLdCredentialSigningNotSupportedError(\n `The requested proofType ${proofType} is not supported`,\n 'unsupported-proof-type'\n )\n }\n\n return this.signatureSuiteRegistry.getByProofType(proofType)\n }\n\n private async prepareSigningSuite(\n agentContext: AgentContext,\n options: {\n proofType: string\n verificationMethodId: string\n allowedPurposes: Array<DidPurpose | 'verificationMethod'>\n date?: string\n controller?: string\n }\n ) {\n const suiteInfo = this.getSigningSuiteInfo(options.proofType)\n\n const dids = agentContext.resolve(DidsApi)\n let resolved: Awaited<ReturnType<typeof dids.resolveVerificationMethodFromCreatedDidRecord>>\n try {\n resolved = await dids.resolveVerificationMethodFromCreatedDidRecord(\n options.verificationMethodId,\n options.allowedPurposes\n )\n } catch (error) {\n if (error instanceof RecordNotFoundError) {\n throw new W3cJsonLdCredentialSigningNotSupportedError(\n error.message,\n 'verification-method-not-controlled',\n error\n )\n }\n if (\n error instanceof CredoError &&\n error.message ===\n `Unable to locate verification method with id '${options.verificationMethodId}' in purposes ${options.allowedPurposes}`\n ) {\n throw new W3cJsonLdCredentialSigningNotSupportedError(error.message, 'verification-method-not-found', error)\n }\n throw error\n }\n\n const { verificationMethod: nativeVerificationMethod, publicJwk } = resolved\n\n if (!suiteInfo.verificationMethodTypes.includes(nativeVerificationMethod.type)) {\n throw new W3cJsonLdCredentialSigningNotSupportedError(\n `Unsupported verification method type '${nativeVerificationMethod.type}' for proof type '${options.proofType}'. Supported types are: ${suiteInfo.verificationMethodTypes.join(', ')}`,\n 'unsupported-verification-method-type'\n )\n }\n\n const documentLoader = this.jsonLdModuleConfig.documentLoader(agentContext)\n const loaderResult = await documentLoader(options.verificationMethodId)\n const framedVerificationMethod =\n typeof loaderResult.document === 'string' ? JSON.parse(loaderResult.document) : loaderResult.document\n\n const WalletKeyPair = createKmsKeyPairClass(agentContext)\n\n // Instantiate suite to validate verification method and framing context\n const SuiteClass = suiteInfo.suiteClass\n const validationSuite = new SuiteClass({\n LDKeyClass: WalletKeyPair,\n proof: {\n verificationMethod: options.verificationMethodId,\n },\n useNativeCanonize: false,\n date: options.date ?? w3cDate(),\n })\n\n await validationSuite.assertVerificationMethod(framedVerificationMethod)\n\n const suitesForKey = this.signatureSuiteRegistry.getAllByPublicJwkType(publicJwk)\n if (!suitesForKey.some(({ suiteClass }) => suiteClass === suiteInfo.suiteClass)) {\n throw new W3cJsonLdCredentialSigningNotSupportedError(\n 'The key type of the verification method does not match the suite',\n 'unsupported-key-type'\n )\n }\n\n const keyPair = new WalletKeyPair({\n controller:\n options.controller ?? (framedVerificationMethod.controller as string) ?? nativeVerificationMethod.controller,\n id: options.verificationMethodId,\n publicJwk,\n })\n\n const suite = new SuiteClass({\n key: keyPair,\n LDKeyClass: WalletKeyPair,\n proof: {\n verificationMethod: options.verificationMethodId,\n },\n useNativeCanonize: false,\n date: options.date ?? w3cDate(),\n })\n\n return { suite, suiteInfo, keyPair, WalletKeyPair }\n }\n\n private getSignatureSuitesForCredential(agentContext: AgentContext, credential: W3cJsonLdVerifiableCredential) {\n const WalletKeyPair = createKmsKeyPairClass(agentContext)\n\n let proofs = credential.proof\n\n if (!Array.isArray(proofs)) {\n proofs = [proofs]\n }\n\n return proofs.map((proof) => {\n const SuiteClass = this.signatureSuiteRegistry.getByProofType(proof.type).suiteClass\n return new SuiteClass({\n LDKeyClass: WalletKeyPair,\n proof: {\n verificationMethod: proof.verificationMethod,\n },\n date: proof.created,\n useNativeCanonize: false,\n })\n })\n }\n\n private assertNoAnonCredsW3cCredentialProof(\n proofsInput: W3cJsonLdVerifiableCredential['proof'] | W3cJsonLdVerifiablePresentation['proof']\n ) {\n const proofs = asArray(proofsInput)\n const hasAnonCredsW3cCredentialProof = proofs.some(\n (proof) =>\n proof.type === 'DataIntegrityProof' &&\n 'cryptosuite' in proof &&\n proof.cryptosuite === ANONCREDS_W3C_CREDENTIAL_CRYPTOSUITE\n )\n\n if (hasAnonCredsW3cCredentialProof) {\n throw new CredoError(\n 'W3C credential proof with cryptosuite anoncreds-2023 must be verified through the anoncreds W3C credential path, not the generic linked-data verifier'\n )\n }\n }\n}\n"],"mappings":"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"}