@credo-ts/core 0.7.3 → 0.7.4

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.
Files changed (92) hide show
  1. package/build/agent/TrustedIssuerContext.d.mts +11 -1
  2. package/build/agent/TrustedIssuerContext.d.mts.map +1 -1
  3. package/build/agent/TrustedIssuerContext.mjs +7 -0
  4. package/build/agent/TrustedIssuerContext.mjs.map +1 -1
  5. package/build/agent/TrustedIssuersForVerification.d.mts +11 -1
  6. package/build/agent/TrustedIssuersForVerification.d.mts.map +1 -1
  7. package/build/index.d.mts +3 -3
  8. package/build/index.mjs +2 -2
  9. package/build/modules/dcql/DcqlService.d.mts.map +1 -1
  10. package/build/modules/dcql/DcqlService.mjs +24 -12
  11. package/build/modules/dcql/DcqlService.mjs.map +1 -1
  12. package/build/modules/dids/domain/verificationMethod/JsonWebKey2020.d.mts +24 -24
  13. package/build/modules/dids/methods/jwk/DidJwk.d.mts +24 -24
  14. package/build/modules/dids/services/DidResolverService.d.mts +4 -0
  15. package/build/modules/dids/services/DidResolverService.d.mts.map +1 -1
  16. package/build/modules/dids/services/DidResolverService.mjs +21 -5
  17. package/build/modules/dids/services/DidResolverService.mjs.map +1 -1
  18. package/build/modules/kms/KeyManagementApi.d.mts +14 -14
  19. package/build/modules/kms/jwk/jwa.d.mts +1 -1
  20. package/build/modules/kms/jwk/knownJwk.d.mts +4 -4
  21. package/build/modules/kms/jwk/kty/ec/P256PublicJwk.d.mts +1 -1
  22. package/build/modules/kms/jwk/kty/ec/P384PublicJwk.d.mts +1 -1
  23. package/build/modules/kms/jwk/kty/ec/P521PublicJwk.d.mts +1 -1
  24. package/build/modules/kms/jwk/kty/ec/Secp256k1PublicJwk.d.mts +1 -1
  25. package/build/modules/kms/jwk/kty/okp/Ed25519PublicJwk.d.mts +2 -2
  26. package/build/modules/kms/jwk/kty/okp/X25519PublicJwk.d.mts +1 -1
  27. package/build/modules/kms/jwk/kty/okp/okpJwk.d.mts +2 -2
  28. package/build/modules/kms/options/KmsCreateKeyOptions.d.mts +3 -3
  29. package/build/modules/kms/options/KmsSignOptions.d.mts +1 -1
  30. package/build/modules/kms/options/KmsVerifyOptions.d.mts +2 -2
  31. package/build/modules/mdoc/repository/MdocRecord.d.mts +1 -1
  32. package/build/modules/sd-jwt-vc/repository/SdJwtVcRecord.d.mts +1 -1
  33. package/build/modules/sd-jwt-vc/utils.mjs +4 -4
  34. package/build/modules/sd-jwt-vc/utils.mjs.map +1 -1
  35. package/build/modules/vc/W3cCredentialServiceOptions.d.mts +5 -5
  36. package/build/modules/vc/W3cCredentialServiceOptions.d.mts.map +1 -1
  37. package/build/modules/vc/W3cV2CredentialService.d.mts +5 -1
  38. package/build/modules/vc/W3cV2CredentialService.d.mts.map +1 -1
  39. package/build/modules/vc/W3cV2CredentialService.mjs +72 -26
  40. package/build/modules/vc/W3cV2CredentialService.mjs.map +1 -1
  41. package/build/modules/vc/W3cV2CredentialServiceOptions.d.mts +14 -6
  42. package/build/modules/vc/W3cV2CredentialServiceOptions.d.mts.map +1 -1
  43. package/build/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.d.mts +0 -18
  44. package/build/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.d.mts.map +1 -1
  45. package/build/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.mjs +38 -36
  46. package/build/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.mjs.map +1 -1
  47. package/build/modules/vc/data-integrity/v2-di-utils.mjs +17 -35
  48. package/build/modules/vc/data-integrity/v2-di-utils.mjs.map +1 -1
  49. package/build/modules/vc/jwt-vc/W3cJwtCredentialService.d.mts +0 -23
  50. package/build/modules/vc/jwt-vc/W3cJwtCredentialService.d.mts.map +1 -1
  51. package/build/modules/vc/jwt-vc/W3cJwtCredentialService.mjs +17 -68
  52. package/build/modules/vc/jwt-vc/W3cJwtCredentialService.mjs.map +1 -1
  53. package/build/modules/vc/jwt-vc/W3cV2JwtCredentialService.d.mts.map +1 -1
  54. package/build/modules/vc/jwt-vc/W3cV2JwtCredentialService.mjs +11 -17
  55. package/build/modules/vc/jwt-vc/W3cV2JwtCredentialService.mjs.map +1 -1
  56. package/build/modules/vc/linked-data-proofs/W3cJsonLdCredentialService.d.mts +5 -0
  57. package/build/modules/vc/linked-data-proofs/W3cJsonLdCredentialService.d.mts.map +1 -1
  58. package/build/modules/vc/linked-data-proofs/W3cJsonLdCredentialService.mjs +18 -4
  59. package/build/modules/vc/linked-data-proofs/W3cJsonLdCredentialService.mjs.map +1 -1
  60. package/build/modules/vc/models/W3cV2VerifyResult.d.mts +6 -0
  61. package/build/modules/vc/models/W3cV2VerifyResult.d.mts.map +1 -1
  62. package/build/modules/vc/resolveSigner.mjs +74 -0
  63. package/build/modules/vc/resolveSigner.mjs.map +1 -0
  64. package/build/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.d.mts.map +1 -1
  65. package/build/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.mjs +16 -18
  66. package/build/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.mjs.map +1 -1
  67. package/build/modules/vc/sd-jwt-vc/disclosureFrame.d.mts +1 -1
  68. package/build/modules/vc/sd-jwt-vc/disclosureFrame.d.mts.map +1 -1
  69. package/build/modules/vc/sd-jwt-vc/disclosureFrame.mjs +2 -1
  70. package/build/modules/vc/sd-jwt-vc/disclosureFrame.mjs.map +1 -1
  71. package/build/modules/vc/v2-jwt-utils.mjs +54 -55
  72. package/build/modules/vc/v2-jwt-utils.mjs.map +1 -1
  73. package/build/modules/x509/X509ModuleConfig.d.mts +5 -13
  74. package/build/modules/x509/X509ModuleConfig.d.mts.map +1 -1
  75. package/build/modules/x509/X509ModuleConfig.mjs +2 -1
  76. package/build/modules/x509/X509ModuleConfig.mjs.map +1 -1
  77. package/build/modules/x509/X509RevocationService.d.mts.map +1 -1
  78. package/build/modules/x509/X509RevocationService.mjs +17 -20
  79. package/build/modules/x509/X509RevocationService.mjs.map +1 -1
  80. package/build/modules/x509/X509Service.mjs +1 -1
  81. package/build/modules/x509/X509Service.mjs.map +1 -1
  82. package/build/modules/x509/X509ServiceOptions.d.mts +4 -6
  83. package/build/modules/x509/X509ServiceOptions.d.mts.map +1 -1
  84. package/build/modules/x509/X509ValidationOptions.d.mts +19 -2
  85. package/build/modules/x509/X509ValidationOptions.d.mts.map +1 -1
  86. package/build/modules/x509/X509ValidationOptions.mjs +21 -1
  87. package/build/modules/x509/X509ValidationOptions.mjs.map +1 -1
  88. package/build/modules/x509/index.d.mts +2 -2
  89. package/build/modules/x509/index.mjs +2 -2
  90. package/build/modules/x509/utils/crlFetcher.mjs +1 -11
  91. package/build/modules/x509/utils/crlFetcher.mjs.map +1 -1
  92. package/package.json +1 -1
@@ -1 +1 @@
1
- {"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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"}
1
+ {"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 { GetTrustedIssuersForCredential, 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 { assertControlledByDid } from '../resolveSigner'\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 holders are the signers of the presentation proofs, which vc-js has already verified\n // for their proof purpose.\n const holderProofPurpose = options.purpose?.term ?? 'authentication'\n const holders = await Promise.all(\n asArray(options.presentation.proof)\n .filter((proof) => proof.proofPurpose === holderProofPurpose)\n .map((proof) => this.resolveSigner(agentContext, proof.verificationMethod))\n )\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 holders.some((holder) => validateCredentialSubjectAuthentication(credentialSubjectIds, holder).isValid)\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[] | GetTrustedIssuersForCredential\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 (\n !verificationMethod.startsWith('did:') ||\n (await this.resolveSigner(agentContext, verificationMethod)) !== issuerDid\n ) {\n throw new CredoError(\n `The proof verification method '${verificationMethod}' does not match the credential issuer did '${issuerDid}'.`\n )\n }\n\n await TrustedIssuerContext.ensureTrustedCredentialSigner(\n agentContext,\n {\n signer: { method: 'did', didUrl: verificationMethod },\n verification: { type: 'credential', credential },\n },\n trustedIssuers\n )\n }\n }\n\n /**\n * Resolves the DID that signed with a verification method, loading it through the configured\n * document loader like vc-js does. vc-js has already validated its proof purpose.\n */\n private async resolveSigner(agentContext: AgentContext, verificationMethodId: string) {\n const did = parseDid(verificationMethodId).did\n const { document } = await this.jsonLdModuleConfig.documentLoader(agentContext)(verificationMethodId)\n assertControlledByDid({ id: verificationMethodId, controller: document.controller }, did)\n\n return did\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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"}
@@ -100,6 +100,12 @@ export type W3cV2PresentationCredentialEntryResult = W3cV2VerifyResult<W3cV2Cred
100
100
  * is signed by at least one of the credential subject ids.
101
101
  */
102
102
  credentialSubjectAuthentication: SingleValidationResult;
103
+ /**
104
+ * Whether a credential bound to a key with `cnf` is presented with that key. Valid when the
105
+ * credential has no `cnf`, which includes an SD-JWT credential whose `cnf` disclosure was left out.
106
+ * Callers that require holder binding must check that the credential has a `cnf`.
107
+ */
108
+ holderBinding: SingleValidationResult;
103
109
  }>;
104
110
  //#endregion
105
111
  //# sourceMappingURL=W3cV2VerifyResult.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"W3cV2VerifyResult.d.mts","names":[],"sources":["../../../../src/modules/vc/models/W3cV2VerifyResult.ts"],"mappings":";;YAEY,8BAA8B,kBAAkB;iBAE3C;;;;;EAKf;;;;EAKA,cAAc,kBAAkB;;;;;EAMhC,mBAAmB;;;;;EAMnB,QAAQ;;UAGA,kBAAkB;;;;;EAK1B;;;;EAKA,aAAa,QAAQ;;;;;EAMrB,QAAQ;;UAGA;;;;;EAKR,WAAW;;;;;EAMX,gBAAgB;;;;EAKhB,WAAW;;;;;EAMX,kBAAkB;;;;;EAMlB,gBAAgB;;UAGR;;;;;EAKR,WAAW;;;;EAKX,uBAAuB;;;;;;;;;;;;EAavB,gBAAgB;;YAGN,yCAAyC,kBACnD;;;;;;;;;;;;EAYE,iCAAiC"}
1
+ {"version":3,"file":"W3cV2VerifyResult.d.mts","names":[],"sources":["../../../../src/modules/vc/models/W3cV2VerifyResult.ts"],"mappings":";;YAEY,8BAA8B,kBAAkB;iBAE3C;;;;;EAKf;;;;EAKA,cAAc,kBAAkB;;;;;EAMhC,mBAAmB;;;;;EAMnB,QAAQ;;UAGA,kBAAkB;;;;;EAK1B;;;;EAKA,aAAa,QAAQ;;;;;EAMrB,QAAQ;;UAGA;;;;;EAKR,WAAW;;;;;EAMX,gBAAgB;;;;EAKhB,WAAW;;;;;EAMX,kBAAkB;;;;;EAMlB,gBAAgB;;UAGR;;;;;EAKR,WAAW;;;;EAKX,uBAAuB;;;;;;;;;;;;EAavB,gBAAgB;;YAGN,yCAAyC,kBACnD;;;;;;;;;;;;EAYE,iCAAiC;;;;;;EAOjC,eAAe"}
@@ -0,0 +1,74 @@
1
+ import { CredoError } from "../../error/CredoError.mjs";
2
+ import "../../error/index.mjs";
3
+ import { isDid } from "../../utils/did.mjs";
4
+ import "../../utils/index.mjs";
5
+ import { PublicJwk } from "../kms/jwk/PublicJwk.mjs";
6
+ import "../kms/index.mjs";
7
+ import { getSupportedVerificationMethodTypesForPublicJwk } from "../dids/domain/key-type/keyDidMapping.mjs";
8
+ import { DidsApi } from "../dids/DidsApi.mjs";
9
+ import "../dids/index.mjs";
10
+ //#region src/modules/vc/resolveSigner.ts
11
+ /**
12
+ * Resolves the verification method of a signature and the DID that signed with it, following
13
+ * Controlled Identifiers 1.0 §3.3 ("Retrieve Verification Method"). The verification method must be
14
+ * listed under `purpose` in the DID document of its own DID, and be controlled by that DID.
15
+ *
16
+ * @param purpose omit when the proof purpose is already validated
17
+ */
18
+ async function resolveSigner(agentContext, verificationMethodId, purpose) {
19
+ const didDocument = await agentContext.dependencyManager.resolve(DidsApi).resolveDidDocument(verificationMethodId);
20
+ const verificationMethod = didDocument.dereferenceKey(verificationMethodId, purpose);
21
+ assertControlledByDid(verificationMethod, didDocument.id);
22
+ return {
23
+ verificationMethod,
24
+ signer: didDocument.id
25
+ };
26
+ }
27
+ /**
28
+ * Resolves the signer of a JWT from its `kid`, or from the `iss` and `alg` when there is no
29
+ * `kid`. When `iss` is present, it must be the signer.
30
+ */
31
+ async function resolveJwtSigner(agentContext, { kid, iss, alg, purpose }) {
32
+ let resolved;
33
+ if (kid?.startsWith("#")) {
34
+ if (!iss || !isDid(iss)) throw new CredoError(`JWT 'iss' MUST be a did when 'kid' is a relative did url`);
35
+ resolved = await resolveSigner(agentContext, `${iss}${kid}`, purpose);
36
+ } else if (kid && isDid(kid)) resolved = await resolveSigner(agentContext, kid, purpose);
37
+ else {
38
+ if (!iss) throw new CredoError(`JWT 'iss' MUST be present in payload when no 'kid' is specified`);
39
+ const jwkClass = PublicJwk.supportedPublicJwkClassForSignatureAlgorithm(alg);
40
+ const didDocument = await agentContext.dependencyManager.resolve(DidsApi).resolveDidDocument(iss);
41
+ const verificationMethods = didDocument.findVerificationMethodsByTypeAndPurpose(getSupportedVerificationMethodTypesForPublicJwk(jwkClass), purpose);
42
+ if (verificationMethods.length !== 1) throw new CredoError(`${verificationMethods.length === 0 ? "No" : "Multiple"} verification methods found for signer '${iss}' and key type '${jwkClass.name}' for alg '${alg}'. Unable to determine which public key is associated with the JWT.`);
43
+ assertControlledByDid(verificationMethods[0], didDocument.id);
44
+ resolved = {
45
+ verificationMethod: verificationMethods[0],
46
+ signer: didDocument.id
47
+ };
48
+ }
49
+ if (iss && resolved.signer !== iss) throw new CredoError(`JWT is signed by '${resolved.signer}', but its 'iss' is '${iss}'`);
50
+ return resolved;
51
+ }
52
+ /**
53
+ * Validates that the `issuer` of a credential or the `holder` of a presentation is the signer. A
54
+ * missing `holder` makes no claim, so it passes.
55
+ */
56
+ function validateSignerIsExpectedParty({ verificationMethod, signer }, expectedSigner, role) {
57
+ if (!expectedSigner || signer === expectedSigner) return { isValid: true };
58
+ const description = role === "issuer" ? `Credential is signed using verification method ${verificationMethod.id}, while the issuer of the credential is '${expectedSigner}'` : `Presentation is signed using verification method ${verificationMethod.id}, while the holder of the presentation is '${expectedSigner}'`;
59
+ return {
60
+ isValid: false,
61
+ error: new CredoError(description)
62
+ };
63
+ }
64
+ /**
65
+ * A DID document can name any controller for its keys, so only the DID of the document that lists
66
+ * the verification method is accepted.
67
+ */
68
+ function assertControlledByDid(verificationMethod, did) {
69
+ if (verificationMethod.controller !== did) throw new CredoError(`Verification method '${verificationMethod.id}' is controlled by '${verificationMethod.controller}', not by the DID document '${did}' it is listed in`);
70
+ }
71
+ //#endregion
72
+ export { assertControlledByDid, resolveJwtSigner, resolveSigner, validateSignerIsExpectedParty };
73
+
74
+ //# sourceMappingURL=resolveSigner.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveSigner.mjs","names":[],"sources":["../../../src/modules/vc/resolveSigner.ts"],"sourcesContent":["import type { AgentContext } from '../../agent'\nimport { CredoError } from '../../error'\nimport { isDid } from '../../utils'\nimport { type DidPurpose, DidsApi, type VerificationMethod } from '../dids'\nimport { getSupportedVerificationMethodTypesForPublicJwk } from '../dids/domain/key-type/keyDidMapping'\nimport { type KnownJwaSignatureAlgorithm, PublicJwk } from '../kms'\nimport type { SingleValidationResult } from './models/W3cVerifyResult'\n\nexport interface ResolvedSigner {\n verificationMethod: VerificationMethod\n\n /** The DID of the DID document that lists and controls `verificationMethod` */\n signer: string\n}\n\n/**\n * Resolves the verification method of a signature and the DID that signed with it, following\n * Controlled Identifiers 1.0 §3.3 (\"Retrieve Verification Method\"). The verification method must be\n * listed under `purpose` in the DID document of its own DID, and be controlled by that DID.\n *\n * @param purpose omit when the proof purpose is already validated\n */\nexport async function resolveSigner(\n agentContext: AgentContext,\n verificationMethodId: string,\n purpose?: DidPurpose[]\n): Promise<ResolvedSigner> {\n const didDocument = await agentContext.dependencyManager.resolve(DidsApi).resolveDidDocument(verificationMethodId)\n\n const verificationMethod = didDocument.dereferenceKey(verificationMethodId, purpose)\n assertControlledByDid(verificationMethod, didDocument.id)\n\n return { verificationMethod, signer: didDocument.id }\n}\n\n/**\n * Resolves the signer of a JWT from its `kid`, or from the `iss` and `alg` when there is no\n * `kid`. When `iss` is present, it must be the signer.\n */\nexport async function resolveJwtSigner(\n agentContext: AgentContext,\n { kid, iss, alg, purpose }: { kid?: string; iss?: string; alg: KnownJwaSignatureAlgorithm; purpose: DidPurpose[] }\n): Promise<ResolvedSigner> {\n let resolved: ResolvedSigner\n\n if (kid?.startsWith('#')) {\n if (!iss || !isDid(iss)) {\n throw new CredoError(`JWT 'iss' MUST be a did when 'kid' is a relative did url`)\n }\n\n resolved = await resolveSigner(agentContext, `${iss}${kid}`, purpose)\n } else if (kid && isDid(kid)) {\n resolved = await resolveSigner(agentContext, kid, purpose)\n } else {\n if (!iss) {\n throw new CredoError(`JWT 'iss' MUST be present in payload when no 'kid' is specified`)\n }\n\n const jwkClass = PublicJwk.supportedPublicJwkClassForSignatureAlgorithm(alg)\n const didDocument = await agentContext.dependencyManager.resolve(DidsApi).resolveDidDocument(iss)\n const verificationMethods = didDocument.findVerificationMethodsByTypeAndPurpose(\n getSupportedVerificationMethodTypesForPublicJwk(jwkClass),\n purpose\n )\n\n if (verificationMethods.length !== 1) {\n throw new CredoError(\n `${verificationMethods.length === 0 ? 'No' : 'Multiple'} verification methods found for signer '${iss}' and key type '${jwkClass.name}' for alg '${alg}'. Unable to determine which public key is associated with the JWT.`\n )\n }\n\n assertControlledByDid(verificationMethods[0], didDocument.id)\n resolved = { verificationMethod: verificationMethods[0], signer: didDocument.id }\n }\n\n if (iss && resolved.signer !== iss) {\n throw new CredoError(`JWT is signed by '${resolved.signer}', but its 'iss' is '${iss}'`)\n }\n\n return resolved\n}\n\n/**\n * Validates that the `issuer` of a credential or the `holder` of a presentation is the signer. A\n * missing `holder` makes no claim, so it passes.\n */\nexport function validateSignerIsExpectedParty(\n { verificationMethod, signer }: ResolvedSigner,\n expectedSigner: string | null | undefined,\n role: 'issuer' | 'holder'\n): SingleValidationResult {\n if (!expectedSigner || signer === expectedSigner) return { isValid: true }\n\n const description =\n role === 'issuer'\n ? `Credential is signed using verification method ${verificationMethod.id}, while the issuer of the credential is '${expectedSigner}'`\n : `Presentation is signed using verification method ${verificationMethod.id}, while the holder of the presentation is '${expectedSigner}'`\n\n return { isValid: false, error: new CredoError(description) }\n}\n\n/**\n * A DID document can name any controller for its keys, so only the DID of the document that lists\n * the verification method is accepted.\n */\nexport function assertControlledByDid(verificationMethod: { id: string; controller?: unknown }, did: string) {\n if (verificationMethod.controller !== did) {\n throw new CredoError(\n `Verification method '${verificationMethod.id}' is controlled by '${verificationMethod.controller}', not by the DID document '${did}' it is listed in`\n )\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAsBA,eAAsB,cACpB,cACA,sBACA,SACyB;CACzB,MAAM,cAAc,MAAM,aAAa,kBAAkB,QAAQ,OAAO,CAAC,CAAC,mBAAmB,oBAAoB;CAEjH,MAAM,qBAAqB,YAAY,eAAe,sBAAsB,OAAO;CACnF,sBAAsB,oBAAoB,YAAY,EAAE;CAExD,OAAO;EAAE;EAAoB,QAAQ,YAAY;CAAG;AACtD;;;;;AAMA,eAAsB,iBACpB,cACA,EAAE,KAAK,KAAK,KAAK,WACQ;CACzB,IAAI;CAEJ,IAAI,KAAK,WAAW,GAAG,GAAG;EACxB,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,GACpB,MAAM,IAAI,WAAW,0DAA0D;EAGjF,WAAW,MAAM,cAAc,cAAc,GAAG,MAAM,OAAO,OAAO;CACtE,OAAO,IAAI,OAAO,MAAM,GAAG,GACzB,WAAW,MAAM,cAAc,cAAc,KAAK,OAAO;MACpD;EACL,IAAI,CAAC,KACH,MAAM,IAAI,WAAW,iEAAiE;EAGxF,MAAM,WAAW,UAAU,6CAA6C,GAAG;EAC3E,MAAM,cAAc,MAAM,aAAa,kBAAkB,QAAQ,OAAO,CAAC,CAAC,mBAAmB,GAAG;EAChG,MAAM,sBAAsB,YAAY,wCACtC,gDAAgD,QAAQ,GACxD,OACF;EAEA,IAAI,oBAAoB,WAAW,GACjC,MAAM,IAAI,WACR,GAAG,oBAAoB,WAAW,IAAI,OAAO,WAAW,0CAA0C,IAAI,kBAAkB,SAAS,KAAK,aAAa,IAAI,oEACzJ;EAGF,sBAAsB,oBAAoB,IAAI,YAAY,EAAE;EAC5D,WAAW;GAAE,oBAAoB,oBAAoB;GAAI,QAAQ,YAAY;EAAG;CAClF;CAEA,IAAI,OAAO,SAAS,WAAW,KAC7B,MAAM,IAAI,WAAW,qBAAqB,SAAS,OAAO,uBAAuB,IAAI,EAAE;CAGzF,OAAO;AACT;;;;;AAMA,SAAgB,8BACd,EAAE,oBAAoB,UACtB,gBACA,MACwB;CACxB,IAAI,CAAC,kBAAkB,WAAW,gBAAgB,OAAO,EAAE,SAAS,KAAK;CAEzE,MAAM,cACJ,SAAS,WACL,kDAAkD,mBAAmB,GAAG,2CAA2C,eAAe,KAClI,oDAAoD,mBAAmB,GAAG,6CAA6C,eAAe;CAE5I,OAAO;EAAE,SAAS;EAAO,OAAO,IAAI,WAAW,WAAW;CAAE;AAC9D;;;;;AAMA,SAAgB,sBAAsB,oBAA0D,KAAa;CAC3G,IAAI,mBAAmB,eAAe,KACpC,MAAM,IAAI,WACR,wBAAwB,mBAAmB,GAAG,sBAAsB,mBAAmB,WAAW,8BAA8B,IAAI,kBACtI;AAEJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"W3cV2SdJwtCredentialService.d.mts","names":[],"sources":["../../../../src/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.ts"],"mappings":";;;;;;;;;;;;;;;;;qBAwDa;;;;EAIE,eACX,cAAc,cACd,SAAS,kCACR,QAAQ;;;;;;;EA+CE,iBACX,cAAc,cACd,SAAS,oCACR,QAAQ;;;;;;;EAsIE,iBACX,cAAc,cACd,SAAS,oCACR,QAAQ;;;;;;;EA4CE,mBACX,cAAc,cACd,SAAS,sCACR,QAAQ;EA+HE,QACX,cAAc,cACd,SAAS,6BACR,QAAQ;;;;EAeJ,2BACL,wBACA,kBAAkB,aACjB;EAKI,yBAAyB,wBAAwB,gBAAgB,cAAc;UAK9E;UAIA;UASA;UAoCA"}
1
+ {"version":3,"file":"W3cV2SdJwtCredentialService.d.mts","names":[],"sources":["../../../../src/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.ts"],"mappings":";;;;;;;;;;;;;;;;;qBAyDa;;;;EAIE,eACX,cAAc,cACd,SAAS,kCACR,QAAQ;;;;;;;EAiDE,iBACX,cAAc,cACd,SAAS,oCACR,QAAQ;;;;;;;EAkIE,iBACX,cAAc,cACd,SAAS,oCACR,QAAQ;;;;;;;EA4CE,mBACX,cAAc,cACd,SAAS,sCACR,QAAQ;EAiHE,QACX,cAAc,cACd,SAAS,6BACR,QAAQ;;;;EAeJ,2BACL,wBACA,kBAAkB,aACjB;EAKI,yBAAyB,wBAAwB,gBAAgB,cAAc;UAK9E;UAIA;UASA;UAoCA"}
@@ -14,12 +14,13 @@ import "../../kms/index.mjs";
14
14
  import { getPublicJwkFromVerificationMethod } from "../../dids/domain/key-type/keyDidMapping.mjs";
15
15
  import { TrustedIssuerContext } from "../../../agent/TrustedIssuerContext.mjs";
16
16
  import { validateVc2ContextBaseline, validateVc2CredentialStatus, validateVc2CredentialValidityPeriod } from "../validators.mjs";
17
+ import { validateSignerIsExpectedParty } from "../resolveSigner.mjs";
17
18
  import "../../../crypto/index.mjs";
18
19
  import { extractKeyFromHolderBinding, getSdJwtHashingAlgorithm, getSdJwtSigner, getSdJwtVerifier, parseHolderBindingFromCredential, setJwkAlgFromJwtHeader } from "../../sd-jwt-vc/utils.mjs";
19
20
  import { sdJwtVcHasher } from "./W3cV2SdJwt.mjs";
20
21
  import { W3cV2SdJwtVerifiableCredential } from "./W3cV2SdJwtVerifiableCredential.mjs";
21
22
  import { W3cV2SdJwtVerifiablePresentation } from "./W3cV2SdJwtVerifiablePresentation.mjs";
22
- import { extractHolderFromPresentationCredentials, getVerificationMethodForJwt, validateAndResolveVerificationMethod } from "../v2-jwt-utils.mjs";
23
+ import { extractHolderFromPresentationCredentials, getSignerForJwt, validateAndResolveVerificationMethod } from "../v2-jwt-utils.mjs";
23
24
  import { validateW3cV2SdJwtDisclosureFrame } from "./disclosureFrame.mjs";
24
25
  import { applyDisclosuresForPaths, applyDisclosuresForPayload } from "../../sd-jwt-vc/disclosureFrame.mjs";
25
26
  import { SDJwtInstance } from "@sd-jwt/core";
@@ -32,7 +33,7 @@ let W3cV2SdJwtCredentialService = class W3cV2SdJwtCredentialService {
32
33
  MessageValidator.validateSync(options.credential);
33
34
  const payload = JsonTransformer.toJSON(options.credential);
34
35
  payload.iat = nowInSeconds();
35
- payload.cnf = options.holder ? (await extractKeyFromHolderBinding(agentContext, options.holder)).cnf : void 0;
36
+ payload.cnf = options.holder ? (await extractKeyFromHolderBinding(agentContext, options.holder, { didPurposes: ["authentication"] })).cnf : void 0;
36
37
  const publicJwk = await validateAndResolveVerificationMethod(agentContext, options.verificationMethod, ["assertionMethod"]);
37
38
  const disclosureFrame = options.disclosureFrame;
38
39
  this.validateDisclosureFrame(disclosureFrame);
@@ -88,9 +89,10 @@ let W3cV2SdJwtCredentialService = class W3cV2SdJwtCredentialService {
88
89
  };
89
90
  return validationResults;
90
91
  }
91
- const issuerVerificationMethod = await getVerificationMethodForJwt(agentContext, credential, ["assertionMethod"]);
92
+ const issuer = await getSignerForJwt(agentContext, credential, ["assertionMethod"]);
93
+ const issuerVerificationMethod = issuer.verificationMethod;
92
94
  const issuerPublicKey = getPublicJwkFromVerificationMethod(issuerVerificationMethod);
93
- await TrustedIssuerContext.ensureTrustedSigner(agentContext, {
95
+ await TrustedIssuerContext.ensureTrustedCredentialSigner(agentContext, {
94
96
  signer: {
95
97
  method: "did",
96
98
  didUrl: issuerVerificationMethod.id
@@ -101,7 +103,7 @@ let W3cV2SdJwtCredentialService = class W3cV2SdJwtCredentialService {
101
103
  }
102
104
  }, options.trustedIssuers);
103
105
  const holderBinding = parseHolderBindingFromCredential(credential.sdJwt.prettyClaims);
104
- const holder = holderBinding ? await extractKeyFromHolderBinding(agentContext, holderBinding) : void 0;
106
+ const holder = holderBinding ? await extractKeyFromHolderBinding(agentContext, holderBinding, { didPurposes: ["authentication"] }) : void 0;
105
107
  setJwkAlgFromJwtHeader(issuerPublicKey, credential.sdJwt.header.alg);
106
108
  if (holder && credential.sdJwt.kbJwt) setJwkAlgFromJwtHeader(holder.publicJwk, credential.sdJwt.kbJwt.header?.alg);
107
109
  sdJwt.config({
@@ -109,7 +111,11 @@ let W3cV2SdJwtCredentialService = class W3cV2SdJwtCredentialService {
109
111
  kbVerifier: holder ? getSdJwtVerifier(agentContext, holder.publicJwk) : void 0
110
112
  });
111
113
  try {
112
- await sdJwt.verify(credential.encoded, { skewSeconds: agentContext.config.validitySkewSeconds });
114
+ await sdJwt.verify(credential.encoded, {
115
+ skewSeconds: agentContext.config.validitySkewSeconds,
116
+ keyBindingNonce: options.keyBinding?.nonce,
117
+ expectedKeyBindingAudience: options.keyBinding?.audience
118
+ });
113
119
  validationResults.validations.signature = { isValid: true };
114
120
  } catch (error) {
115
121
  validationResults.validations.signature = {
@@ -117,11 +123,7 @@ let W3cV2SdJwtCredentialService = class W3cV2SdJwtCredentialService {
117
123
  error
118
124
  };
119
125
  }
120
- if (credential.resolvedCredential.issuerId !== issuerVerificationMethod.controller) validationResults.validations.issuerIsSigner = {
121
- isValid: false,
122
- error: new CredoError(`Credential is signed using verification method ${issuerVerificationMethod.id}, while the issuer of the credential is '${credential.resolvedCredential.issuerId}'`)
123
- };
124
- else validationResults.validations.issuerIsSigner = { isValid: true };
126
+ validationResults.validations.issuerIsSigner = validateSignerIsExpectedParty(issuer, credential.resolvedCredential.issuerId, "issuer");
125
127
  validationResults.isValid = Object.values(validationResults.validations).every((validation) => validation?.isValid === true);
126
128
  return validationResults;
127
129
  } catch (error) {
@@ -193,8 +195,8 @@ let W3cV2SdJwtCredentialService = class W3cV2SdJwtCredentialService {
193
195
  };
194
196
  return validationResults;
195
197
  }
196
- const proverVerificationMethod = await getVerificationMethodForJwt(agentContext, presentation, ["authentication"]);
197
- const proverPublicKey = getPublicJwkFromVerificationMethod(proverVerificationMethod);
198
+ const prover = await getSignerForJwt(agentContext, presentation, ["authentication"]);
199
+ const proverPublicKey = getPublicJwkFromVerificationMethod(prover.verificationMethod);
198
200
  const holderBinding = parseHolderBindingFromCredential(presentation.sdJwt.prettyClaims);
199
201
  const holder = holderBinding ? await extractKeyFromHolderBinding(agentContext, holderBinding) : void 0;
200
202
  setJwkAlgFromJwtHeader(proverPublicKey, presentation.sdJwt.header.alg);
@@ -212,11 +214,7 @@ let W3cV2SdJwtCredentialService = class W3cV2SdJwtCredentialService {
212
214
  error
213
215
  };
214
216
  }
215
- if (presentation.resolvedPresentation.holderId && proverVerificationMethod.controller !== presentation.resolvedPresentation.holderId) validationResults.presentation.validations.holderIsSigner = {
216
- isValid: false,
217
- error: new CredoError(`Presentation is signed using verification method ${proverVerificationMethod.id}, while the holder of the presentation is '${presentation.resolvedPresentation.holderId}'`)
218
- };
219
- else validationResults.presentation.validations.holderIsSigner = { isValid: true };
217
+ validationResults.presentation.validations.holderIsSigner = validateSignerIsExpectedParty(prover, presentation.resolvedPresentation.holderId, "holder");
220
218
  validationResults.presentation.isValid = Object.values(validationResults.presentation.validations).every((validation) => validation.isValid);
221
219
  validationResults.isValid = validationResults.presentation.isValid;
222
220
  return validationResults;
@@ -1 +1 @@
1
- {"version":3,"file":"W3cV2SdJwtCredentialService.mjs","names":[],"sources":["../../../../src/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.ts"],"sourcesContent":["import { type DisclosureFrame, type PresentationFrame, type SDJWTConfig, SDJwtInstance } from '@sd-jwt/core'\nimport type { AgentContext } from '../../../agent/context'\nimport { TrustedIssuerContext } from '../../../agent/TrustedIssuerContext'\nimport { JwtPayload } from '../../../crypto'\nimport { CredoError } from '../../../error'\nimport { injectable } from '../../../plugins'\nimport type { JsonObject } from '../../../types'\nimport { asArray, JsonTransformer, MessageValidator, nowInSeconds, TypedArrayEncoder } from '../../../utils'\nimport { getPublicJwkFromVerificationMethod } from '../../dids/domain/key-type/keyDidMapping'\nimport { KeyManagementApi } from '../../kms'\nimport type { IDisclosureFrame } from '../../sd-jwt-vc'\nimport { applyDisclosuresForPaths, applyDisclosuresForPayload, type ClaimPath } from '../../sd-jwt-vc/disclosureFrame'\nimport {\n extractKeyFromHolderBinding,\n getSdJwtHashingAlgorithm,\n getSdJwtSigner,\n getSdJwtVerifier,\n parseHolderBindingFromCredential,\n setJwkAlgFromJwtHeader,\n} from '../../sd-jwt-vc/utils'\nimport type {\n W3cV2JsonCredential,\n W3cV2JsonPresentation,\n W3cV2VerifyCredentialResult,\n W3cV2VerifyPresentationResult,\n} from '../models'\nimport {\n extractHolderFromPresentationCredentials,\n getVerificationMethodForJwt,\n validateAndResolveVerificationMethod,\n} from '../v2-jwt-utils'\nimport {\n validateVc2ContextBaseline,\n validateVc2CredentialStatus,\n validateVc2CredentialValidityPeriod,\n} from '../validators'\nimport type {\n W3cV2SdJwtSignCredentialOptions,\n W3cV2SdJwtSignPresentationOptions,\n W3cV2SdJwtVcPresentOptions,\n W3cV2SdJwtVerifyCredentialOptions,\n W3cV2SdJwtVerifyPresentationOptions,\n} from '../W3cV2CredentialServiceOptions'\nimport { validateW3cV2SdJwtDisclosureFrame } from './disclosureFrame'\nimport { sdJwtVcHasher } from './W3cV2SdJwt'\nimport { W3cV2SdJwtVerifiableCredential } from './W3cV2SdJwtVerifiableCredential'\nimport { W3cV2SdJwtVerifiablePresentation } from './W3cV2SdJwtVerifiablePresentation'\n\n/**\n * Supports signing and verifying W3C Verifiable Credentials and Presentations\n * secured with Selective Disclosure JSON Web Tokens (SD-JWT).\n *\n * @see https://www.w3.org/TR/vc-data-model/\n * @see https://www.w3.org/TR/vc-jose-cose/#with-sd-jwt\n */\n@injectable()\nexport class W3cV2SdJwtCredentialService {\n /**\n * Signs a credential\n */\n public async signCredential(\n agentContext: AgentContext,\n options: W3cV2SdJwtSignCredentialOptions\n ): Promise<W3cV2SdJwtVerifiableCredential> {\n // Validate the instance\n MessageValidator.validateSync(options.credential)\n\n // The JWT payload is simply the credential\n const payload = JsonTransformer.toJSON(options.credential) as W3cV2JsonCredential\n\n // Add iat and cnf to the payload\n payload.iat = nowInSeconds()\n payload.cnf = options.holder ? (await extractKeyFromHolderBinding(agentContext, options.holder)).cnf : undefined\n\n // Validate and resolve the verification method\n const publicJwk = await validateAndResolveVerificationMethod(agentContext, options.verificationMethod, [\n 'assertionMethod',\n ])\n\n // Validate the disclosure frame\n const disclosureFrame = options.disclosureFrame as DisclosureFrame<W3cV2JsonCredential> | undefined\n this.validateDisclosureFrame(disclosureFrame)\n\n publicJwk.alg = options.alg\n\n const sdJwt = new SDJwtInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n signer: getSdJwtSigner(agentContext, publicJwk),\n hashAlg: getSdJwtHashingAlgorithm(options.hashingAlgorithm),\n signAlg: options.alg,\n })\n\n // Sign SD-JWT\n const compact = await sdJwt.issue<W3cV2JsonCredential>(payload, disclosureFrame, {\n header: {\n typ: 'vc+sd-jwt',\n alg: options.alg,\n kid: options.verificationMethod,\n },\n })\n\n return W3cV2SdJwtVerifiableCredential.fromCompact(compact)\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: W3cV2SdJwtVerifyCredentialOptions\n ): Promise<W3cV2VerifyCredentialResult> {\n const validationResults: W3cV2VerifyCredentialResult = {\n isValid: false,\n validations: {},\n }\n\n const sdJwt = new SDJwtInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n })\n\n try {\n let credential: W3cV2SdJwtVerifiableCredential\n try {\n // If instance is provided as input, we want to validate the credential\n // Otherwise, it is done by fromCompact below\n if (options.credential instanceof W3cV2SdJwtVerifiableCredential) {\n options.credential.validate()\n }\n\n credential =\n options.credential instanceof W3cV2SdJwtVerifiableCredential\n ? options.credential\n : W3cV2SdJwtVerifiableCredential.fromCompact(options.credential)\n\n // Validate JWT payload\n JwtPayload.fromJson(credential.sdJwt.payload).validate({\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n this.logCredentialShouldWarnings(agentContext, credential)\n\n validationResults.validations.dataModel = validateVc2ContextBaseline(credential.resolvedCredential.context)\n if (!validationResults.validations.dataModel.isValid) {\n return validationResults\n }\n\n validationResults.validations.dataModel = {\n isValid: true,\n }\n\n validationResults.validations.validityPeriod = validateVc2CredentialValidityPeriod({\n validFrom: credential.resolvedCredential.validFrom,\n validUntil: credential.resolvedCredential.validUntil,\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n validationResults.validations.credentialStatus = validateVc2CredentialStatus({\n credentialStatus: credential.resolvedCredential.credentialStatus,\n credentialFormat: 'SD-JWT',\n verifyCredentialStatus: options.verifyCredentialStatus,\n })\n } catch (error) {\n validationResults.validations.dataModel = {\n isValid: false,\n error,\n }\n\n return validationResults\n }\n\n const issuerVerificationMethod = await getVerificationMethodForJwt(agentContext, credential, ['assertionMethod'])\n const issuerPublicKey = getPublicJwkFromVerificationMethod(issuerVerificationMethod)\n\n // Ensure the issuer is trusted according to the (optional) `getTrustedIssuersForVerification`\n // callback. For did-based issuers this is a no-op when no trusted issuers are configured,\n // preserving the previous \"trust any valid signature\" behavior. Throws when the issuer is not trusted.\n await TrustedIssuerContext.ensureTrustedSigner(\n agentContext,\n {\n signer: { method: 'did', didUrl: issuerVerificationMethod.id },\n verification: { type: 'credential', credential },\n },\n options.trustedIssuers\n )\n\n const holderBinding = parseHolderBindingFromCredential(credential.sdJwt.prettyClaims)\n const holder = holderBinding ? await extractKeyFromHolderBinding(agentContext, holderBinding) : undefined\n\n setJwkAlgFromJwtHeader(issuerPublicKey, credential.sdJwt.header.alg)\n if (holder && credential.sdJwt.kbJwt) {\n setJwkAlgFromJwtHeader(holder.publicJwk, credential.sdJwt.kbJwt.header?.alg)\n }\n\n sdJwt.config({\n verifier: getSdJwtVerifier(agentContext, issuerPublicKey),\n kbVerifier: holder ? getSdJwtVerifier(agentContext, holder.publicJwk) : undefined,\n })\n\n try {\n await sdJwt.verify(credential.encoded, {\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n validationResults.validations.signature = {\n isValid: true,\n }\n } catch (error) {\n validationResults.validations.signature = {\n isValid: false,\n error,\n }\n }\n\n // Validate whether the credential is signed with the 'issuer' id\n // NOTE: this uses the verificationMethod.controller. We may want to use the verificationMethod.id?\n if (credential.resolvedCredential.issuerId !== issuerVerificationMethod.controller) {\n validationResults.validations.issuerIsSigner = {\n isValid: false,\n error: new CredoError(\n `Credential is signed using verification method ${issuerVerificationMethod.id}, while the issuer of the credential is '${credential.resolvedCredential.issuerId}'`\n ),\n }\n } else {\n validationResults.validations.issuerIsSigner = {\n isValid: true,\n }\n }\n\n validationResults.isValid = Object.values(validationResults.validations).every(\n (validation) => validation?.isValid === true\n )\n return validationResults\n } catch (error) {\n validationResults.error = error\n return validationResults\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: W3cV2SdJwtSignPresentationOptions\n ): Promise<W3cV2SdJwtVerifiablePresentation> {\n // Validate the instance\n MessageValidator.validateSync(options.presentation)\n\n // The JWT payload is simply the presentation\n const payload = JsonTransformer.toJSON(options.presentation) as W3cV2JsonPresentation\n\n // Add the nonce and aud to the payload\n payload.nonce = options.challenge\n payload.aud = options.domain\n\n const holder = await extractHolderFromPresentationCredentials(agentContext, options.presentation)\n\n holder.publicJwk.alg = holder.alg\n\n const sdJwt = new SDJwtInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n signer: getSdJwtSigner(agentContext, holder.publicJwk),\n hashAlg: getSdJwtHashingAlgorithm(options.hashingAlgorithm),\n signAlg: holder.alg,\n })\n\n // Validate the disclosure frame\n const disclosureFrame = options.disclosureFrame as DisclosureFrame<W3cV2JsonPresentation> | undefined\n this.validateDisclosureFrame(disclosureFrame)\n\n // Sign SD-JWT\n const compact = await sdJwt.issue<W3cV2JsonPresentation>(payload, disclosureFrame, {\n header: {\n typ: 'vp+sd-jwt',\n alg: holder.alg,\n kid: holder?.cnf?.kid,\n },\n })\n\n return W3cV2SdJwtVerifiablePresentation.fromCompact(compact)\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: W3cV2SdJwtVerifyPresentationOptions\n ): Promise<W3cV2VerifyPresentationResult> {\n const validationResults: W3cV2VerifyPresentationResult = {\n isValid: false,\n presentation: {\n isValid: false,\n validations: {},\n },\n credentialEntries: [],\n }\n\n const sdjwt = new SDJwtInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n })\n\n try {\n let presentation: W3cV2SdJwtVerifiablePresentation\n try {\n // If instance is provided as input, we want to validate the presentation\n if (options.presentation instanceof W3cV2SdJwtVerifiablePresentation) {\n options.presentation.validate()\n }\n\n presentation =\n options.presentation instanceof W3cV2SdJwtVerifiablePresentation\n ? options.presentation\n : W3cV2SdJwtVerifiablePresentation.fromCompact(options.presentation)\n\n // Validate JWT payload\n JwtPayload.fromJson(presentation.sdJwt.payload).validate({\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n this.logPresentationShouldWarnings(agentContext, presentation)\n\n // VC-JOSE-COSE: understood claims MUST be evaluated per verifier policy\n // https://www.w3.org/TR/vc-jose-cose/#validation-algorithm\n if (options.challenge !== presentation.sdJwt.prettyClaims.nonce) {\n throw new CredoError(`JWT payload 'nonce' does not match challenge '${options.challenge}'`)\n }\n\n const audArray = asArray(presentation.sdJwt.prettyClaims.aud)\n if (options.domain && !audArray.includes(options.domain)) {\n throw new CredoError(`JWT payload 'aud' does not include domain '${options.domain}'`)\n }\n\n const contextValidationResult = validateVc2ContextBaseline(presentation.resolvedPresentation.context)\n if (!contextValidationResult.isValid) {\n throw contextValidationResult.error\n }\n\n validationResults.presentation.validations.dataModel = {\n isValid: true,\n }\n } catch (error) {\n validationResults.presentation.validations.dataModel = {\n isValid: false,\n error,\n }\n\n return validationResults\n }\n\n const proverVerificationMethod = await getVerificationMethodForJwt(agentContext, presentation, ['authentication'])\n const proverPublicKey = getPublicJwkFromVerificationMethod(proverVerificationMethod)\n const holderBinding = parseHolderBindingFromCredential(presentation.sdJwt.prettyClaims)\n const holder = holderBinding ? await extractKeyFromHolderBinding(agentContext, holderBinding) : undefined\n\n setJwkAlgFromJwtHeader(proverPublicKey, presentation.sdJwt.header.alg)\n if (holder && presentation.sdJwt.kbJwt) {\n setJwkAlgFromJwtHeader(holder.publicJwk, presentation.sdJwt.kbJwt.header?.alg)\n }\n\n sdjwt.config({\n verifier: getSdJwtVerifier(agentContext, proverPublicKey),\n kbVerifier: holder ? getSdJwtVerifier(agentContext, holder.publicJwk) : undefined,\n })\n\n try {\n await sdjwt.verify(presentation.encoded, {\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n validationResults.presentation.validations.presentationSignature = {\n isValid: true,\n }\n } catch (error) {\n validationResults.presentation.validations.presentationSignature = {\n isValid: false,\n error,\n }\n }\n\n // Validate whether the presentation is signed with the 'holder' id\n // NOTE: this uses the verificationMethod.controller. We may want to use the verificationMethod.id?\n if (\n presentation.resolvedPresentation.holderId &&\n proverVerificationMethod.controller !== presentation.resolvedPresentation.holderId\n ) {\n validationResults.presentation.validations.holderIsSigner = {\n isValid: false,\n error: new CredoError(\n `Presentation is signed using verification method ${proverVerificationMethod.id}, while the holder of the presentation is '${presentation.resolvedPresentation.holderId}'`\n ),\n }\n } else {\n // If no holderId is present, this validation passes by default as there can't be\n // a mismatch between the 'holder' property and the signer of the presentation.\n validationResults.presentation.validations.holderIsSigner = {\n isValid: true,\n }\n }\n\n validationResults.presentation.isValid = Object.values(validationResults.presentation.validations).every(\n (validation) => validation.isValid\n )\n\n // Credential-entry dispatch is orchestrated by W3cV2CredentialService.\n // This service verifies VP container integrity only.\n validationResults.isValid = validationResults.presentation.isValid\n\n return validationResults\n } catch (error) {\n validationResults.error = error\n return validationResults\n }\n }\n\n public async present(\n agentContext: AgentContext,\n options: W3cV2SdJwtVcPresentOptions\n ): Promise<W3cV2SdJwtVerifiableCredential> {\n const originalCompact =\n options.credential instanceof W3cV2SdJwtVerifiableCredential ? options.credential.encoded : options.credential\n\n const presentationFrame = options.presentationFrame as PresentationFrame<W3cV2JsonCredential>\n\n const sdjwt = new SDJwtInstance(this.getBaseSdJwtConfig(agentContext))\n const disclosedCompact = await sdjwt.present(originalCompact, presentationFrame)\n\n return W3cV2SdJwtVerifiableCredential.fromCompact(disclosedCompact)\n }\n\n /**\n * @deprecated use `applyDisclosuresForPaths` instead\n */\n public applyDisclosuresForPayload(\n compactSdJwtVc: string,\n requestedPayload: JsonObject\n ): W3cV2SdJwtVerifiableCredential {\n const sdJwt = applyDisclosuresForPayload(compactSdJwtVc, requestedPayload)\n return W3cV2SdJwtVerifiableCredential.fromCompact(sdJwt)\n }\n\n public applyDisclosuresForPaths(compactSdJwtVc: string, disclosedPaths: ClaimPath[]): W3cV2SdJwtVerifiableCredential {\n const { compact } = applyDisclosuresForPaths(compactSdJwtVc, disclosedPaths)\n return W3cV2SdJwtVerifiableCredential.fromCompact(compact)\n }\n\n private validateDisclosureFrame(disclosureFrame?: DisclosureFrame<W3cV2JsonCredential | W3cV2JsonPresentation>) {\n validateW3cV2SdJwtDisclosureFrame(disclosureFrame as IDisclosureFrame | undefined)\n }\n\n private getBaseSdJwtConfig(agentContext: AgentContext): SDJWTConfig {\n const kms = agentContext.resolve(KeyManagementApi)\n\n return {\n hasher: sdJwtVcHasher,\n saltGenerator: (length) => TypedArrayEncoder.toBase64Url(kms.randomBytes({ length })).slice(0, length),\n }\n }\n\n private logCredentialShouldWarnings(agentContext: AgentContext, credential: W3cV2SdJwtVerifiableCredential) {\n const payload = credential.sdJwt.prettyClaims\n const headerIss = credential.sdJwt.header.iss\n\n if (typeof headerIss === 'string' && typeof payload.iss === 'string' && headerIss !== payload.iss) {\n agentContext.config.logger.warn('VC-JOSE-COSE SHOULD warning: JOSE header iss conflicts with payload iss', {\n format: 'vc+sd-jwt',\n headerIss,\n payloadIss: payload.iss,\n })\n }\n\n if (\n typeof payload.jti === 'string' &&\n credential.resolvedCredential.id &&\n credential.resolvedCredential.id !== payload.jti\n ) {\n agentContext.config.logger.warn('VC-JOSE-COSE SHOULD warning: jti claim conflicts with credential id', {\n format: 'vc+sd-jwt',\n jti: payload.jti,\n credentialId: credential.resolvedCredential.id,\n })\n }\n\n if (typeof payload.sub === 'string' && !credential.resolvedCredential.credentialSubjectIds.includes(payload.sub)) {\n agentContext.config.logger.warn(\n 'VC-JOSE-COSE SHOULD warning: sub claim does not match any credentialSubject.id',\n {\n format: 'vc+sd-jwt',\n sub: payload.sub,\n credentialSubjectIds: credential.resolvedCredential.credentialSubjectIds,\n }\n )\n }\n }\n\n private logPresentationShouldWarnings(agentContext: AgentContext, presentation: W3cV2SdJwtVerifiablePresentation) {\n const payload = presentation.sdJwt.prettyClaims\n const headerIss = presentation.sdJwt.header.iss\n\n if (typeof headerIss === 'string' && typeof payload.iss === 'string' && headerIss !== payload.iss) {\n agentContext.config.logger.warn('VC-JOSE-COSE SHOULD warning: JOSE header iss conflicts with payload iss', {\n format: 'vp+sd-jwt',\n headerIss,\n payloadIss: payload.iss,\n })\n }\n\n if (\n typeof payload.jti === 'string' &&\n presentation.resolvedPresentation.id &&\n presentation.resolvedPresentation.id !== payload.jti\n ) {\n agentContext.config.logger.warn('VC-JOSE-COSE SHOULD warning: jti claim conflicts with presentation id', {\n format: 'vp+sd-jwt',\n jti: payload.jti,\n presentationId: presentation.resolvedPresentation.id,\n })\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"W3cV2SdJwtCredentialService.mjs","names":[],"sources":["../../../../src/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.ts"],"sourcesContent":["import { type DisclosureFrame, type PresentationFrame, type SDJWTConfig, SDJwtInstance } from '@sd-jwt/core'\nimport type { AgentContext } from '../../../agent/context'\nimport { TrustedIssuerContext } from '../../../agent/TrustedIssuerContext'\nimport { JwtPayload } from '../../../crypto'\nimport { CredoError } from '../../../error'\nimport { injectable } from '../../../plugins'\nimport type { JsonObject } from '../../../types'\nimport { asArray, JsonTransformer, MessageValidator, nowInSeconds, TypedArrayEncoder } from '../../../utils'\nimport { getPublicJwkFromVerificationMethod } from '../../dids/domain/key-type/keyDidMapping'\nimport { KeyManagementApi } from '../../kms'\nimport type { IDisclosureFrame } from '../../sd-jwt-vc'\nimport { applyDisclosuresForPaths, applyDisclosuresForPayload, type ClaimPath } from '../../sd-jwt-vc/disclosureFrame'\nimport {\n extractKeyFromHolderBinding,\n getSdJwtHashingAlgorithm,\n getSdJwtSigner,\n getSdJwtVerifier,\n parseHolderBindingFromCredential,\n setJwkAlgFromJwtHeader,\n} from '../../sd-jwt-vc/utils'\nimport type {\n W3cV2JsonCredential,\n W3cV2JsonPresentation,\n W3cV2VerifyCredentialResult,\n W3cV2VerifyPresentationResult,\n} from '../models'\nimport { validateSignerIsExpectedParty } from '../resolveSigner'\nimport {\n extractHolderFromPresentationCredentials,\n getSignerForJwt,\n validateAndResolveVerificationMethod,\n} from '../v2-jwt-utils'\nimport {\n validateVc2ContextBaseline,\n validateVc2CredentialStatus,\n validateVc2CredentialValidityPeriod,\n} from '../validators'\nimport type {\n W3cV2SdJwtSignCredentialOptions,\n W3cV2SdJwtSignPresentationOptions,\n W3cV2SdJwtVcPresentOptions,\n W3cV2SdJwtVerifyCredentialOptions,\n W3cV2SdJwtVerifyPresentationOptions,\n} from '../W3cV2CredentialServiceOptions'\nimport { validateW3cV2SdJwtDisclosureFrame } from './disclosureFrame'\nimport { sdJwtVcHasher } from './W3cV2SdJwt'\nimport { W3cV2SdJwtVerifiableCredential } from './W3cV2SdJwtVerifiableCredential'\nimport { W3cV2SdJwtVerifiablePresentation } from './W3cV2SdJwtVerifiablePresentation'\n\n/**\n * Supports signing and verifying W3C Verifiable Credentials and Presentations\n * secured with Selective Disclosure JSON Web Tokens (SD-JWT).\n *\n * @see https://www.w3.org/TR/vc-data-model/\n * @see https://www.w3.org/TR/vc-jose-cose/#with-sd-jwt\n */\n@injectable()\nexport class W3cV2SdJwtCredentialService {\n /**\n * Signs a credential\n */\n public async signCredential(\n agentContext: AgentContext,\n options: W3cV2SdJwtSignCredentialOptions\n ): Promise<W3cV2SdJwtVerifiableCredential> {\n // Validate the instance\n MessageValidator.validateSync(options.credential)\n\n // The JWT payload is simply the credential\n const payload = JsonTransformer.toJSON(options.credential) as W3cV2JsonCredential\n\n // Add iat and cnf to the payload\n payload.iat = nowInSeconds()\n payload.cnf = options.holder\n ? (await extractKeyFromHolderBinding(agentContext, options.holder, { didPurposes: ['authentication'] })).cnf\n : undefined\n\n // Validate and resolve the verification method\n const publicJwk = await validateAndResolveVerificationMethod(agentContext, options.verificationMethod, [\n 'assertionMethod',\n ])\n\n // Validate the disclosure frame\n const disclosureFrame = options.disclosureFrame as DisclosureFrame<W3cV2JsonCredential> | undefined\n this.validateDisclosureFrame(disclosureFrame)\n\n publicJwk.alg = options.alg\n\n const sdJwt = new SDJwtInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n signer: getSdJwtSigner(agentContext, publicJwk),\n hashAlg: getSdJwtHashingAlgorithm(options.hashingAlgorithm),\n signAlg: options.alg,\n })\n\n // Sign SD-JWT\n const compact = await sdJwt.issue<W3cV2JsonCredential>(payload, disclosureFrame, {\n header: {\n typ: 'vc+sd-jwt',\n alg: options.alg,\n kid: options.verificationMethod,\n },\n })\n\n return W3cV2SdJwtVerifiableCredential.fromCompact(compact)\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: W3cV2SdJwtVerifyCredentialOptions\n ): Promise<W3cV2VerifyCredentialResult> {\n const validationResults: W3cV2VerifyCredentialResult = {\n isValid: false,\n validations: {},\n }\n\n const sdJwt = new SDJwtInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n })\n\n try {\n let credential: W3cV2SdJwtVerifiableCredential\n try {\n // If instance is provided as input, we want to validate the credential\n // Otherwise, it is done by fromCompact below\n if (options.credential instanceof W3cV2SdJwtVerifiableCredential) {\n options.credential.validate()\n }\n\n credential =\n options.credential instanceof W3cV2SdJwtVerifiableCredential\n ? options.credential\n : W3cV2SdJwtVerifiableCredential.fromCompact(options.credential)\n\n // Validate JWT payload\n JwtPayload.fromJson(credential.sdJwt.payload).validate({\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n this.logCredentialShouldWarnings(agentContext, credential)\n\n validationResults.validations.dataModel = validateVc2ContextBaseline(credential.resolvedCredential.context)\n if (!validationResults.validations.dataModel.isValid) {\n return validationResults\n }\n\n validationResults.validations.dataModel = {\n isValid: true,\n }\n\n validationResults.validations.validityPeriod = validateVc2CredentialValidityPeriod({\n validFrom: credential.resolvedCredential.validFrom,\n validUntil: credential.resolvedCredential.validUntil,\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n validationResults.validations.credentialStatus = validateVc2CredentialStatus({\n credentialStatus: credential.resolvedCredential.credentialStatus,\n credentialFormat: 'SD-JWT',\n verifyCredentialStatus: options.verifyCredentialStatus,\n })\n } catch (error) {\n validationResults.validations.dataModel = {\n isValid: false,\n error,\n }\n\n return validationResults\n }\n\n const issuer = await getSignerForJwt(agentContext, credential, ['assertionMethod'])\n const issuerVerificationMethod = issuer.verificationMethod\n const issuerPublicKey = getPublicJwkFromVerificationMethod(issuerVerificationMethod)\n\n // Ensure the issuer is trusted according to the (optional) `getTrustedIssuersForVerification`\n // callback. For did-based issuers this is a no-op when no trusted issuers are configured,\n // preserving the previous \"trust any valid signature\" behavior. Throws when the issuer is not trusted.\n await TrustedIssuerContext.ensureTrustedCredentialSigner(\n agentContext,\n {\n signer: { method: 'did', didUrl: issuerVerificationMethod.id },\n verification: { type: 'credential', credential },\n },\n options.trustedIssuers\n )\n\n const holderBinding = parseHolderBindingFromCredential(credential.sdJwt.prettyClaims)\n const holder = holderBinding\n ? await extractKeyFromHolderBinding(agentContext, holderBinding, { didPurposes: ['authentication'] })\n : undefined\n\n setJwkAlgFromJwtHeader(issuerPublicKey, credential.sdJwt.header.alg)\n if (holder && credential.sdJwt.kbJwt) {\n setJwkAlgFromJwtHeader(holder.publicJwk, credential.sdJwt.kbJwt.header?.alg)\n }\n\n sdJwt.config({\n verifier: getSdJwtVerifier(agentContext, issuerPublicKey),\n kbVerifier: holder ? getSdJwtVerifier(agentContext, holder.publicJwk) : undefined,\n })\n\n try {\n await sdJwt.verify(credential.encoded, {\n skewSeconds: agentContext.config.validitySkewSeconds,\n keyBindingNonce: options.keyBinding?.nonce,\n expectedKeyBindingAudience: options.keyBinding?.audience,\n })\n\n validationResults.validations.signature = {\n isValid: true,\n }\n } catch (error) {\n validationResults.validations.signature = {\n isValid: false,\n error,\n }\n }\n\n validationResults.validations.issuerIsSigner = validateSignerIsExpectedParty(\n issuer,\n credential.resolvedCredential.issuerId,\n 'issuer'\n )\n\n validationResults.isValid = Object.values(validationResults.validations).every(\n (validation) => validation?.isValid === true\n )\n return validationResults\n } catch (error) {\n validationResults.error = error\n return validationResults\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: W3cV2SdJwtSignPresentationOptions\n ): Promise<W3cV2SdJwtVerifiablePresentation> {\n // Validate the instance\n MessageValidator.validateSync(options.presentation)\n\n // The JWT payload is simply the presentation\n const payload = JsonTransformer.toJSON(options.presentation) as W3cV2JsonPresentation\n\n // Add the nonce and aud to the payload\n payload.nonce = options.challenge\n payload.aud = options.domain\n\n const holder = await extractHolderFromPresentationCredentials(agentContext, options.presentation)\n\n holder.publicJwk.alg = holder.alg\n\n const sdJwt = new SDJwtInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n signer: getSdJwtSigner(agentContext, holder.publicJwk),\n hashAlg: getSdJwtHashingAlgorithm(options.hashingAlgorithm),\n signAlg: holder.alg,\n })\n\n // Validate the disclosure frame\n const disclosureFrame = options.disclosureFrame as DisclosureFrame<W3cV2JsonPresentation> | undefined\n this.validateDisclosureFrame(disclosureFrame)\n\n // Sign SD-JWT\n const compact = await sdJwt.issue<W3cV2JsonPresentation>(payload, disclosureFrame, {\n header: {\n typ: 'vp+sd-jwt',\n alg: holder.alg,\n kid: holder?.cnf?.kid,\n },\n })\n\n return W3cV2SdJwtVerifiablePresentation.fromCompact(compact)\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: W3cV2SdJwtVerifyPresentationOptions\n ): Promise<W3cV2VerifyPresentationResult> {\n const validationResults: W3cV2VerifyPresentationResult = {\n isValid: false,\n presentation: {\n isValid: false,\n validations: {},\n },\n credentialEntries: [],\n }\n\n const sdjwt = new SDJwtInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n })\n\n try {\n let presentation: W3cV2SdJwtVerifiablePresentation\n try {\n // If instance is provided as input, we want to validate the presentation\n if (options.presentation instanceof W3cV2SdJwtVerifiablePresentation) {\n options.presentation.validate()\n }\n\n presentation =\n options.presentation instanceof W3cV2SdJwtVerifiablePresentation\n ? options.presentation\n : W3cV2SdJwtVerifiablePresentation.fromCompact(options.presentation)\n\n // Validate JWT payload\n JwtPayload.fromJson(presentation.sdJwt.payload).validate({\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n this.logPresentationShouldWarnings(agentContext, presentation)\n\n // VC-JOSE-COSE: understood claims MUST be evaluated per verifier policy\n // https://www.w3.org/TR/vc-jose-cose/#validation-algorithm\n if (options.challenge !== presentation.sdJwt.prettyClaims.nonce) {\n throw new CredoError(`JWT payload 'nonce' does not match challenge '${options.challenge}'`)\n }\n\n const audArray = asArray(presentation.sdJwt.prettyClaims.aud)\n if (options.domain && !audArray.includes(options.domain)) {\n throw new CredoError(`JWT payload 'aud' does not include domain '${options.domain}'`)\n }\n\n const contextValidationResult = validateVc2ContextBaseline(presentation.resolvedPresentation.context)\n if (!contextValidationResult.isValid) {\n throw contextValidationResult.error\n }\n\n validationResults.presentation.validations.dataModel = {\n isValid: true,\n }\n } catch (error) {\n validationResults.presentation.validations.dataModel = {\n isValid: false,\n error,\n }\n\n return validationResults\n }\n\n const prover = await getSignerForJwt(agentContext, presentation, ['authentication'])\n const proverPublicKey = getPublicJwkFromVerificationMethod(prover.verificationMethod)\n const holderBinding = parseHolderBindingFromCredential(presentation.sdJwt.prettyClaims)\n const holder = holderBinding ? await extractKeyFromHolderBinding(agentContext, holderBinding) : undefined\n\n setJwkAlgFromJwtHeader(proverPublicKey, presentation.sdJwt.header.alg)\n if (holder && presentation.sdJwt.kbJwt) {\n setJwkAlgFromJwtHeader(holder.publicJwk, presentation.sdJwt.kbJwt.header?.alg)\n }\n\n sdjwt.config({\n verifier: getSdJwtVerifier(agentContext, proverPublicKey),\n kbVerifier: holder ? getSdJwtVerifier(agentContext, holder.publicJwk) : undefined,\n })\n\n try {\n await sdjwt.verify(presentation.encoded, {\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n validationResults.presentation.validations.presentationSignature = {\n isValid: true,\n }\n } catch (error) {\n validationResults.presentation.validations.presentationSignature = {\n isValid: false,\n error,\n }\n }\n\n validationResults.presentation.validations.holderIsSigner = validateSignerIsExpectedParty(\n prover,\n presentation.resolvedPresentation.holderId,\n 'holder'\n )\n\n validationResults.presentation.isValid = Object.values(validationResults.presentation.validations).every(\n (validation) => validation.isValid\n )\n\n // Credential-entry dispatch is orchestrated by W3cV2CredentialService.\n // This service verifies VP container integrity only.\n validationResults.isValid = validationResults.presentation.isValid\n\n return validationResults\n } catch (error) {\n validationResults.error = error\n return validationResults\n }\n }\n\n public async present(\n agentContext: AgentContext,\n options: W3cV2SdJwtVcPresentOptions\n ): Promise<W3cV2SdJwtVerifiableCredential> {\n const originalCompact =\n options.credential instanceof W3cV2SdJwtVerifiableCredential ? options.credential.encoded : options.credential\n\n const presentationFrame = options.presentationFrame as PresentationFrame<W3cV2JsonCredential>\n\n const sdjwt = new SDJwtInstance(this.getBaseSdJwtConfig(agentContext))\n const disclosedCompact = await sdjwt.present(originalCompact, presentationFrame)\n\n return W3cV2SdJwtVerifiableCredential.fromCompact(disclosedCompact)\n }\n\n /**\n * @deprecated use `applyDisclosuresForPaths` instead\n */\n public applyDisclosuresForPayload(\n compactSdJwtVc: string,\n requestedPayload: JsonObject\n ): W3cV2SdJwtVerifiableCredential {\n const sdJwt = applyDisclosuresForPayload(compactSdJwtVc, requestedPayload)\n return W3cV2SdJwtVerifiableCredential.fromCompact(sdJwt)\n }\n\n public applyDisclosuresForPaths(compactSdJwtVc: string, disclosedPaths: ClaimPath[]): W3cV2SdJwtVerifiableCredential {\n const { compact } = applyDisclosuresForPaths(compactSdJwtVc, disclosedPaths)\n return W3cV2SdJwtVerifiableCredential.fromCompact(compact)\n }\n\n private validateDisclosureFrame(disclosureFrame?: DisclosureFrame<W3cV2JsonCredential | W3cV2JsonPresentation>) {\n validateW3cV2SdJwtDisclosureFrame(disclosureFrame as IDisclosureFrame | undefined)\n }\n\n private getBaseSdJwtConfig(agentContext: AgentContext): SDJWTConfig {\n const kms = agentContext.resolve(KeyManagementApi)\n\n return {\n hasher: sdJwtVcHasher,\n saltGenerator: (length) => TypedArrayEncoder.toBase64Url(kms.randomBytes({ length })).slice(0, length),\n }\n }\n\n private logCredentialShouldWarnings(agentContext: AgentContext, credential: W3cV2SdJwtVerifiableCredential) {\n const payload = credential.sdJwt.prettyClaims\n const headerIss = credential.sdJwt.header.iss\n\n if (typeof headerIss === 'string' && typeof payload.iss === 'string' && headerIss !== payload.iss) {\n agentContext.config.logger.warn('VC-JOSE-COSE SHOULD warning: JOSE header iss conflicts with payload iss', {\n format: 'vc+sd-jwt',\n headerIss,\n payloadIss: payload.iss,\n })\n }\n\n if (\n typeof payload.jti === 'string' &&\n credential.resolvedCredential.id &&\n credential.resolvedCredential.id !== payload.jti\n ) {\n agentContext.config.logger.warn('VC-JOSE-COSE SHOULD warning: jti claim conflicts with credential id', {\n format: 'vc+sd-jwt',\n jti: payload.jti,\n credentialId: credential.resolvedCredential.id,\n })\n }\n\n if (typeof payload.sub === 'string' && !credential.resolvedCredential.credentialSubjectIds.includes(payload.sub)) {\n agentContext.config.logger.warn(\n 'VC-JOSE-COSE SHOULD warning: sub claim does not match any credentialSubject.id',\n {\n format: 'vc+sd-jwt',\n sub: payload.sub,\n credentialSubjectIds: credential.resolvedCredential.credentialSubjectIds,\n }\n )\n }\n }\n\n private logPresentationShouldWarnings(agentContext: AgentContext, presentation: W3cV2SdJwtVerifiablePresentation) {\n const payload = presentation.sdJwt.prettyClaims\n const headerIss = presentation.sdJwt.header.iss\n\n if (typeof headerIss === 'string' && typeof payload.iss === 'string' && headerIss !== payload.iss) {\n agentContext.config.logger.warn('VC-JOSE-COSE SHOULD warning: JOSE header iss conflicts with payload iss', {\n format: 'vp+sd-jwt',\n headerIss,\n payloadIss: payload.iss,\n })\n }\n\n if (\n typeof payload.jti === 'string' &&\n presentation.resolvedPresentation.id &&\n presentation.resolvedPresentation.id !== payload.jti\n ) {\n agentContext.config.logger.warn('VC-JOSE-COSE SHOULD warning: jti claim conflicts with presentation id', {\n format: 'vp+sd-jwt',\n jti: payload.jti,\n presentationId: presentation.resolvedPresentation.id,\n })\n }\n }\n}\n"],"mappings":"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"}
@@ -7,7 +7,7 @@ import "../../sd-jwt-vc/index.mjs";
7
7
  * @see https://www.w3.org/TR/vc-jose-cose/#securing-with-sd-jwt
8
8
  * @see https://www.w3.org/TR/vc-jose-cose/#securing-vps-sd-jwt
9
9
  */
10
- export declare const NON_DISCLOSEABLE_FIELDS: readonly ["@context", "type", "credentialStatus", "credentialSchema", "relatedResource"];
10
+ export declare const NON_DISCLOSEABLE_FIELDS: readonly ["@context", "type", "credentialStatus", "credentialSchema", "relatedResource", "cnf"];
11
11
  /**
12
12
  * Asserts that a disclosure frame does not make any of the {@link NON_DISCLOSEABLE_FIELDS} of a W3C
13
13
  * VCDM 2.0 credential or presentation selectively disclosable.
@@ -1 +1 @@
1
- {"version":3,"file":"disclosureFrame.d.mts","names":[],"sources":["../../../../src/modules/vc/sd-jwt-vc/disclosureFrame.ts"],"mappings":";;;;;;;;;qBASa;;;;;;;;wBAeG,kCAAkC,kBAAkB"}
1
+ {"version":3,"file":"disclosureFrame.d.mts","names":[],"sources":["../../../../src/modules/vc/sd-jwt-vc/disclosureFrame.ts"],"mappings":";;;;;;;;;qBASa;;;;;;;;wBAiBG,kCAAkC,kBAAkB"}
@@ -12,7 +12,8 @@ const NON_DISCLOSEABLE_FIELDS = [
12
12
  "type",
13
13
  "credentialStatus",
14
14
  "credentialSchema",
15
- "relatedResource"
15
+ "relatedResource",
16
+ "cnf"
16
17
  ];
17
18
  /**
18
19
  * Asserts that a disclosure frame does not make any of the {@link NON_DISCLOSEABLE_FIELDS} of a W3C
@@ -1 +1 @@
1
- {"version":3,"file":"disclosureFrame.mjs","names":[],"sources":["../../../../src/modules/vc/sd-jwt-vc/disclosureFrame.ts"],"sourcesContent":["import { CredoError } from '../../../error'\nimport type { IDisclosureFrame } from '../../sd-jwt-vc'\n\n/**\n * List of fields that cannot be selectively disclosed.\n *\n * @see https://www.w3.org/TR/vc-jose-cose/#securing-with-sd-jwt\n * @see https://www.w3.org/TR/vc-jose-cose/#securing-vps-sd-jwt\n */\nexport const NON_DISCLOSEABLE_FIELDS = [\n '@context',\n 'type',\n 'credentialStatus',\n 'credentialSchema',\n 'relatedResource',\n] as const\n\n/**\n * Asserts that a disclosure frame does not make any of the {@link NON_DISCLOSEABLE_FIELDS} of a W3C\n * VCDM 2.0 credential or presentation selectively disclosable.\n *\n * Only the top level of the frame is checked. A nested claim that happens to share a name with a\n * non-discloseable field, such as `credentialSubject.type`, may be selectively disclosed.\n */\nexport function validateW3cV2SdJwtDisclosureFrame(disclosureFrame?: IDisclosureFrame) {\n if (!disclosureFrame) return\n\n for (const field of NON_DISCLOSEABLE_FIELDS) {\n if (disclosureFrame[field]) {\n throw new CredoError(`'${field}' property cannot be selectively disclosed`)\n }\n\n if (Array.isArray(disclosureFrame._sd) && disclosureFrame._sd.includes(field)) {\n throw new CredoError(`'${field}' property cannot be selectively disclosed`)\n }\n }\n}\n"],"mappings":";;;;;;;;;AASA,MAAa,0BAA0B;CACrC;CACA;CACA;CACA;CACA;AACF;;;;;;;;AASA,SAAgB,kCAAkC,iBAAoC;CACpF,IAAI,CAAC,iBAAiB;CAEtB,KAAK,MAAM,SAAS,yBAAyB;EAC3C,IAAI,gBAAgB,QAClB,MAAM,IAAI,WAAW,IAAI,MAAM,2CAA2C;EAG5E,IAAI,MAAM,QAAQ,gBAAgB,GAAG,KAAK,gBAAgB,IAAI,SAAS,KAAK,GAC1E,MAAM,IAAI,WAAW,IAAI,MAAM,2CAA2C;CAE9E;AACF"}
1
+ {"version":3,"file":"disclosureFrame.mjs","names":[],"sources":["../../../../src/modules/vc/sd-jwt-vc/disclosureFrame.ts"],"sourcesContent":["import { CredoError } from '../../../error'\nimport type { IDisclosureFrame } from '../../sd-jwt-vc'\n\n/**\n * List of fields that cannot be selectively disclosed.\n *\n * @see https://www.w3.org/TR/vc-jose-cose/#securing-with-sd-jwt\n * @see https://www.w3.org/TR/vc-jose-cose/#securing-vps-sd-jwt\n */\nexport const NON_DISCLOSEABLE_FIELDS = [\n '@context',\n 'type',\n 'credentialStatus',\n 'credentialSchema',\n 'relatedResource',\n // A verifier can't tell an omitted `cnf` disclosure from a credential without holder binding\n 'cnf',\n] as const\n\n/**\n * Asserts that a disclosure frame does not make any of the {@link NON_DISCLOSEABLE_FIELDS} of a W3C\n * VCDM 2.0 credential or presentation selectively disclosable.\n *\n * Only the top level of the frame is checked. A nested claim that happens to share a name with a\n * non-discloseable field, such as `credentialSubject.type`, may be selectively disclosed.\n */\nexport function validateW3cV2SdJwtDisclosureFrame(disclosureFrame?: IDisclosureFrame) {\n if (!disclosureFrame) return\n\n for (const field of NON_DISCLOSEABLE_FIELDS) {\n if (disclosureFrame[field]) {\n throw new CredoError(`'${field}' property cannot be selectively disclosed`)\n }\n\n if (Array.isArray(disclosureFrame._sd) && disclosureFrame._sd.includes(field)) {\n throw new CredoError(`'${field}' property cannot be selectively disclosed`)\n }\n }\n}\n"],"mappings":";;;;;;;;;AASA,MAAa,0BAA0B;CACrC;CACA;CACA;CACA;CACA;CAEA;AACF;;;;;;;;AASA,SAAgB,kCAAkC,iBAAoC;CACpF,IAAI,CAAC,iBAAiB;CAEtB,KAAK,MAAM,SAAS,yBAAyB;EAC3C,IAAI,gBAAgB,QAClB,MAAM,IAAI,WAAW,IAAI,MAAM,2CAA2C;EAG5E,IAAI,MAAM,QAAQ,gBAAgB,GAAG,KAAK,gBAAgB,IAAI,SAAS,KAAK,GAC1E,MAAM,IAAI,WAAW,IAAI,MAAM,2CAA2C;CAE9E;AACF"}