@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":"W3cV2CredentialService.mjs","names":[],"sources":["../../../src/modules/vc/W3cV2CredentialService.ts"],"sourcesContent":["import type { AgentContext } from '../../agent/context'\nimport { CredoError } from '../../error'\nimport { injectable } from '../../plugins'\nimport type { Query, QueryOptions } from '../../storage/StorageService'\nimport { asArray } from '../../utils/array'\nimport {\n W3cV2DataIntegrityCredentialService,\n type W3cV2DataIntegrityResolvedPresentation,\n W3cV2DataIntegrityVerifiableCredential,\n W3cV2DataIntegrityVerifiablePresentation,\n} from './data-integrity'\nimport { getSignerForDataIntegrityProof } from './data-integrity/v2-di-utils'\nimport { W3cV2JwtVerifiableCredential, W3cV2JwtVerifiablePresentation } from './jwt-vc'\nimport { W3cV2JwtCredentialService } from './jwt-vc/W3cV2JwtCredentialService'\nimport type {\n W3cV2PresentationCredentialEntry,\n W3cV2PresentationCredentialEntryResult,\n W3cV2VerifiableCredential,\n W3cV2VerifiablePresentation,\n W3cV2VerifyCredentialResult,\n W3cV2VerifyPresentationResult,\n} from './models'\nimport {\n ClaimFormat,\n decodeW3cV2VerifiablePresentation,\n W3cV2EnvelopedVerifiableCredential,\n W3cV2EnvelopedVerifiablePresentation,\n} from './models'\nimport { decodeW3cV2VerifiableCredential } from './models/credential/W3cV2VerifiableCredential'\nimport type { W3cV2Presentation } from './models/presentation/W3cV2Presentation'\nimport { W3cV2CredentialRecord, W3cV2CredentialRepository } from './repository'\nimport {\n W3cV2SdJwtCredentialService,\n W3cV2SdJwtVerifiableCredential,\n W3cV2SdJwtVerifiablePresentation,\n} from './sd-jwt-vc'\nimport { getVerificationMethodForJwt } from './v2-jwt-utils'\nimport type {\n W3cV2DiSignCredentialOptions,\n W3cV2DiSignPresentationOptions,\n W3cV2DiVerifyCredentialOptions,\n W3cV2DiVerifyPresentationOptions,\n W3cV2JwtVerifyCredentialOptions,\n W3cV2JwtVerifyPresentationOptions,\n W3cV2SdJwtVerifyCredentialOptions,\n W3cV2SdJwtVerifyPresentationOptions,\n W3cV2SignCredentialOptions,\n W3cV2SignPresentationOptions,\n W3cV2StoreCredentialOptions,\n W3cV2VerifyCredentialOptions,\n W3cV2VerifyPresentationOptions,\n} from './W3cV2CredentialServiceOptions'\n\n@injectable()\nexport class W3cV2CredentialService {\n private w3cV2CredentialRepository: W3cV2CredentialRepository\n private w3cV2SdJwtCredentialService: W3cV2SdJwtCredentialService\n private w3cV2JwtCredentialService: W3cV2JwtCredentialService\n private w3cV2DataIntegrityCredentialService: W3cV2DataIntegrityCredentialService\n\n public constructor(\n w3cV2CredentialRepository: W3cV2CredentialRepository,\n w3cV2SdJwtCredentialService: W3cV2SdJwtCredentialService,\n w3cV2JwtCredentialService: W3cV2JwtCredentialService,\n w3cV2DataIntegrityCredentialService: W3cV2DataIntegrityCredentialService\n ) {\n this.w3cV2CredentialRepository = w3cV2CredentialRepository\n this.w3cV2SdJwtCredentialService = w3cV2SdJwtCredentialService\n this.w3cV2JwtCredentialService = w3cV2JwtCredentialService\n this.w3cV2DataIntegrityCredentialService = w3cV2DataIntegrityCredentialService\n }\n\n /**\n * Signs a credential\n *\n * @param credential the credential to be signed\n * @returns the signed credential\n */\n public async signCredential<Format extends ClaimFormat.JwtW3cVc | ClaimFormat.SdJwtW3cVc | ClaimFormat.DiVc>(\n agentContext: AgentContext,\n options: W3cV2SignCredentialOptions<Format>\n ): Promise<W3cV2VerifiableCredential<Format>> {\n if (options.format === ClaimFormat.JwtW3cVc) {\n const signed = await this.w3cV2JwtCredentialService.signCredential(agentContext, options)\n return signed as W3cV2VerifiableCredential<Format>\n }\n if (options.format === ClaimFormat.SdJwtW3cVc) {\n const signed = await this.w3cV2SdJwtCredentialService.signCredential(agentContext, options)\n return signed as W3cV2VerifiableCredential<Format>\n }\n if (options.format === ClaimFormat.DiVc) {\n const signed = await this.w3cV2DataIntegrityCredentialService.signCredential(\n agentContext,\n options as W3cV2DiSignCredentialOptions\n )\n return signed as W3cV2VerifiableCredential<Format>\n }\n throw new CredoError(`Unsupported format in options. Format must be either 'vc+jwt', 'vc+sd-jwt', or 'di_vc'`)\n }\n\n /**\n * Verifies the signature(s) of a credential\n */\n public async verifyCredential(\n agentContext: AgentContext,\n options: W3cV2VerifyCredentialOptions\n ): Promise<W3cV2VerifyCredentialResult> {\n const credential =\n typeof options.credential === 'string' ? decodeW3cV2VerifiableCredential(options.credential) : options.credential\n\n if (credential instanceof W3cV2JwtVerifiableCredential) {\n return this.w3cV2JwtCredentialService.verifyCredential(agentContext, {\n ...options,\n credential,\n } as W3cV2JwtVerifyCredentialOptions)\n }\n\n if (credential instanceof W3cV2SdJwtVerifiableCredential) {\n return this.w3cV2SdJwtCredentialService.verifyCredential(agentContext, {\n ...options,\n credential,\n } as W3cV2SdJwtVerifyCredentialOptions)\n }\n\n if (credential instanceof W3cV2DataIntegrityVerifiableCredential) {\n return this.w3cV2DataIntegrityCredentialService.verifyCredential(agentContext, {\n ...options,\n credential,\n } as W3cV2DiVerifyCredentialOptions)\n }\n\n throw new CredoError(\n 'Unsupported credential type in options. Credential must be either a W3cV2JwtVerifiableCredential, a W3cV2SdJwtVerifiableCredential, or a W3cV2DataIntegrityVerifiableCredential'\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<Format extends ClaimFormat.JwtW3cVp | ClaimFormat.SdJwtW3cVp | ClaimFormat.DiVp>(\n agentContext: AgentContext,\n options: W3cV2SignPresentationOptions<Format>\n ): Promise<W3cV2VerifiablePresentation<Format>> {\n if (options.format === ClaimFormat.JwtW3cVp) {\n const signed = await this.w3cV2JwtCredentialService.signPresentation(agentContext, options)\n return signed as W3cV2VerifiablePresentation<Format>\n }\n if (options.format === ClaimFormat.SdJwtW3cVp) {\n const signed = await this.w3cV2SdJwtCredentialService.signPresentation(agentContext, options)\n return signed as W3cV2VerifiablePresentation<Format>\n }\n if (options.format === ClaimFormat.DiVp) {\n const signed = await this.w3cV2DataIntegrityCredentialService.signPresentation(\n agentContext,\n options as W3cV2DiSignPresentationOptions\n )\n return signed as W3cV2VerifiablePresentation<Format>\n }\n throw new CredoError(`Unsupported format in options. Format must be either 'vp+jwt', 'vp+sd-jwt', or 'di_vp'`)\n }\n\n /**\n * Verifies a W3C V2 verifiable presentation and each enclosed credential entry.\n *\n * Flow:\n * 1. Verifies the outer VP using the format-specific service (`vp+jwt` or `vp+sd-jwt`).\n * 2. Derives the presenter identifier (holder id, or JWT verification method controller fallback).\n * 3. Recursively walks enclosed entries and verifies each credential entry with the matching\n * credential verifier (`vc+jwt` or `vc+sd-jwt`) based on the actual enclosed format.\n * 4. Adds `credentialSubjectAuthentication` validation to each credential result by checking\n * whether the authenticated presenter matches at least one credentialSubject id.\n *\n * Current support and constraints:\n * - Compact string presentations are accepted for `vp+jwt` and `vp+sd-jwt` and normalized\n * to typed presentation instances before routing.\n * - `di_vp` routes through the DI credential service for outer-VP verification.\n * - `di_vc` entries route through the DI credential service for entry verification.\n * - Nested VP entries are treated as invalid. VC 2.0 verifiable presentations support VC entries,\n * not VP-within-VP entries.\n *\n * Return semantics:\n * - `presentation` contains the outer VP verification result.\n * - `credentialEntries` contains one result per traversed credential entry, including unsupported\n * entries as invalid results.\n * - Top-level `isValid` is true only if the outer VP and all credential entry validations are valid.\n *\n * @param agentContext The framework agent context used for resolution and cryptographic checks.\n * @param options Verification input containing the presentation to verify.\n * @returns Aggregated presentation and credential-entry verification result.\n */\n public async verifyPresentation(\n agentContext: AgentContext,\n options: W3cV2VerifyPresentationOptions\n ): Promise<W3cV2VerifyPresentationResult> {\n const presentation =\n typeof options.presentation === 'string'\n ? decodeW3cV2VerifiablePresentation(options.presentation)\n : options.presentation\n\n const validationResults: W3cV2VerifyPresentationResult = {\n isValid: false,\n presentation: {\n isValid: false,\n validations: {},\n },\n credentialEntries: [],\n }\n\n let entries: W3cV2PresentationCredentialEntry[] = []\n let signerId: string | undefined\n\n // Phase 1: verify the outer secured VP envelope and derive the authenticated presenter.\n if (presentation instanceof W3cV2JwtVerifiablePresentation) {\n const presentationResult = await this.w3cV2JwtCredentialService.verifyPresentation(agentContext, {\n ...options,\n presentation,\n } as W3cV2JwtVerifyPresentationOptions)\n validationResults.presentation = presentationResult.presentation\n\n if (!presentationResult.presentation.isValid) {\n validationResults.isValid = false\n return validationResults\n }\n\n const holderId = presentation.resolvedPresentation.holderId\n if (holderId) {\n signerId = holderId\n } else {\n try {\n const verificationMethod = await getVerificationMethodForJwt(agentContext, presentation, ['authentication'])\n signerId = verificationMethod.controller\n } catch (error) {\n validationResults.isValid = false\n validationResults.error = error\n return validationResults\n }\n }\n entries = this.extractCredentialEntriesFromPresentation(presentation)\n } else if (presentation instanceof W3cV2SdJwtVerifiablePresentation) {\n const presentationResult = await this.w3cV2SdJwtCredentialService.verifyPresentation(agentContext, {\n ...options,\n presentation,\n } as W3cV2SdJwtVerifyPresentationOptions)\n validationResults.presentation = presentationResult.presentation\n\n if (!presentationResult.presentation.isValid) {\n validationResults.isValid = false\n return validationResults\n }\n\n const holderId = presentation.resolvedPresentation.holderId\n if (holderId) {\n signerId = holderId\n } else {\n try {\n const verificationMethod = await getVerificationMethodForJwt(agentContext, presentation, ['authentication'])\n signerId = verificationMethod.controller\n } catch (error) {\n validationResults.isValid = false\n validationResults.error = error\n return validationResults\n }\n }\n entries = this.extractCredentialEntriesFromPresentation(presentation)\n } else if (presentation instanceof W3cV2DataIntegrityVerifiablePresentation) {\n const presentationResult = await this.w3cV2DataIntegrityCredentialService.verifyPresentation(agentContext, {\n ...options,\n presentation,\n } as W3cV2DiVerifyPresentationOptions)\n validationResults.presentation = presentationResult.presentation\n\n if (!presentationResult.presentation.isValid) {\n validationResults.isValid = false\n return validationResults\n }\n\n signerId = presentation.resolvedPresentation.holderId\n if (!signerId) {\n try {\n // The holder is optional in VCDM 2.0, so fall back to the identity that authenticated the\n // presentation, mirroring how the JWT and SD-JWT branches above derive their signer.\n // No expected controller is passed: with no declared holder there is nothing to\n // disambiguate against, so an ambiguous proof set is rejected rather than guessed at.\n signerId = await getSignerForDataIntegrityProof(\n agentContext,\n presentation.securedPresentation,\n 'authentication'\n )\n } catch (error) {\n validationResults.isValid = false\n validationResults.error = error\n return validationResults\n }\n }\n\n entries = this.extractCredentialEntriesFromPresentation(presentation)\n } else {\n throw new CredoError(\n 'Unsupported credential type in options. Presentation must be either a W3cV2JwtVerifiablePresentation, a W3cV2SdJwtVerifiablePresentation, or a W3cV2DataIntegrityVerifiablePresentation'\n )\n }\n\n // Phase 2: walk enclosed credential entries and verify recursively by entry format.\n validationResults.credentialEntries = (\n await Promise.all(entries.map((entry) => this.verifyPresentationEntry(agentContext, entry, signerId)))\n ).flat()\n\n validationResults.isValid =\n validationResults.presentation.isValid && validationResults.credentialEntries.every((entry) => entry.isValid)\n\n return validationResults\n }\n\n private async verifyPresentationEntry(\n agentContext: AgentContext,\n entry: W3cV2PresentationCredentialEntry,\n signerId: string\n ): Promise<W3cV2PresentationCredentialEntryResult[]> {\n if (entry instanceof W3cV2DataIntegrityVerifiablePresentation) {\n return [\n this.createInvalidCredentialEntryResult(\n new CredoError('Nested verifiable presentation entries are not supported in VC 2.0 presentations.')\n ),\n ]\n }\n\n if (entry instanceof W3cV2DataIntegrityVerifiableCredential) {\n const credentialResult = await this.w3cV2DataIntegrityCredentialService.verifyCredential(agentContext, {\n credential: entry,\n } as W3cV2DiVerifyCredentialOptions)\n\n return [\n this.mergeCredentialSubjectAuthenticationValidation(\n credentialResult,\n signerId,\n entry.resolvedCredential?.credentialSubjectIds ?? []\n ),\n ]\n }\n\n if (entry instanceof W3cV2EnvelopedVerifiablePresentation) {\n return [\n this.createInvalidCredentialEntryResult(\n new CredoError('Nested verifiable presentation entries are not supported in VC 2.0 presentations.')\n ),\n ]\n }\n\n if (!(entry instanceof W3cV2EnvelopedVerifiableCredential)) {\n return [\n this.createInvalidCredentialEntryResult(new CredoError('Unsupported credential entry type in presentation.')),\n ]\n }\n\n const enclosed = entry.envelopedCredential\n let credentialResult: W3cV2VerifyCredentialResult\n\n if (enclosed instanceof W3cV2JwtVerifiableCredential) {\n credentialResult = await this.w3cV2JwtCredentialService.verifyCredential(agentContext, {\n credential: enclosed,\n } as W3cV2JwtVerifyCredentialOptions)\n } else if (enclosed instanceof W3cV2SdJwtVerifiableCredential) {\n credentialResult = await this.w3cV2SdJwtCredentialService.verifyCredential(agentContext, {\n credential: enclosed,\n } as W3cV2SdJwtVerifyCredentialOptions)\n } else {\n return [\n this.createInvalidCredentialEntryResult(\n new CredoError(\n `Credential entry uses '${this.getClaimFormat(enclosed) ?? 'an unsupported enclosed credential format'}'.`\n )\n ),\n ]\n }\n\n return [\n this.mergeCredentialSubjectAuthenticationValidation(\n credentialResult,\n signerId,\n entry.resolvedCredential.credentialSubjectIds\n ),\n ]\n }\n\n private extractCredentialEntriesFromPresentation(\n presentation:\n | W3cV2JwtVerifiablePresentation\n | W3cV2SdJwtVerifiablePresentation\n | W3cV2DataIntegrityVerifiablePresentation\n ): W3cV2PresentationCredentialEntry[] {\n return this.extractCredentialEntriesFromResolvedPresentation(presentation.resolvedPresentation)\n }\n\n private extractCredentialEntriesFromResolvedPresentation(\n resolvedPresentation: Pick<W3cV2Presentation, 'verifiableCredential'> | W3cV2DataIntegrityResolvedPresentation\n ): W3cV2PresentationCredentialEntry[] {\n return asArray(resolvedPresentation.verifiableCredential) as W3cV2PresentationCredentialEntry[]\n }\n\n private createInvalidCredentialEntryResult(error: Error): W3cV2PresentationCredentialEntryResult {\n return {\n isValid: false,\n error,\n validations: {},\n }\n }\n\n private getClaimFormat(value: unknown): string | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined\n\n const candidate = value as { claimFormat?: unknown }\n return typeof candidate.claimFormat === 'string' ? candidate.claimFormat : undefined\n }\n\n private mergeCredentialSubjectAuthenticationValidation(\n credentialResult: W3cV2VerifyCredentialResult,\n signerId: string,\n credentialSubjectIds: string[]\n ) {\n const presentationAuthenticatesCredentialSubject = credentialSubjectIds.some((subjectId) => signerId === subjectId)\n\n const credentialSubjectAuthentication =\n credentialSubjectIds.length > 0 && !presentationAuthenticatesCredentialSubject\n ? {\n isValid: false,\n error: new CredoError(\n 'Credential has one or more credentialSubject ids, but presentation does not authenticate credential subject'\n ),\n }\n : {\n isValid: true,\n }\n\n return {\n ...credentialResult,\n isValid: credentialResult.isValid && credentialSubjectAuthentication.isValid,\n validations: {\n ...credentialResult.validations,\n credentialSubjectAuthentication,\n },\n }\n }\n\n /**\n * Writes a credential to storage\n *\n * @param record the credential to be stored\n * @returns the credential record that was written to storage\n */\n public async storeCredential(\n agentContext: AgentContext,\n options: W3cV2StoreCredentialOptions\n ): Promise<W3cV2CredentialRecord> {\n // Store the w3cV2 credential record\n await this.w3cV2CredentialRepository.save(agentContext, options.record)\n\n return options.record\n }\n\n public async removeCredentialRecord(agentContext: AgentContext, id: string) {\n await this.w3cV2CredentialRepository.deleteById(agentContext, id)\n }\n\n public async getAllCredentialRecords(agentContext: AgentContext): Promise<W3cV2CredentialRecord[]> {\n return await this.w3cV2CredentialRepository.getAll(agentContext)\n }\n\n public async getCredentialRecordById(agentContext: AgentContext, id: string): Promise<W3cV2CredentialRecord> {\n return await this.w3cV2CredentialRepository.getById(agentContext, id)\n }\n\n public async findCredentialsByQuery(\n agentContext: AgentContext,\n query: Query<W3cV2CredentialRecord>,\n queryOptions?: QueryOptions\n ): Promise<W3cV2VerifiableCredential[]> {\n const result = await this.w3cV2CredentialRepository.findByQuery(agentContext, query, queryOptions)\n return result.map((record) => record.firstCredential)\n }\n\n public async findCredentialRecordByQuery(\n agentContext: AgentContext,\n query: Query<W3cV2CredentialRecord>\n ): Promise<W3cV2VerifiableCredential | undefined> {\n const result = await this.w3cV2CredentialRepository.findSingleByQuery(agentContext, query)\n return result?.firstCredential\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"W3cV2CredentialService.mjs","names":[],"sources":["../../../src/modules/vc/W3cV2CredentialService.ts"],"sourcesContent":["import type { AgentContext } from '../../agent/context'\nimport type { GetTrustedIssuersForCredential, TrustedIssuerDid } from '../../agent/TrustedIssuersForVerification'\nimport { CredoError } from '../../error'\nimport { injectable } from '../../plugins'\nimport type { Query, QueryOptions } from '../../storage/StorageService'\nimport { asArray } from '../../utils/array'\nimport { getPublicJwkFromVerificationMethod } from '../dids'\nimport { extractKeyFromHolderBinding, parseHolderBindingFromCredential } from '../sd-jwt-vc/utils'\nimport {\n W3cV2DataIntegrityCredentialService,\n type W3cV2DataIntegrityResolvedPresentation,\n W3cV2DataIntegrityVerifiableCredential,\n W3cV2DataIntegrityVerifiablePresentation,\n} from './data-integrity'\nimport { resolveDataIntegritySigner } from './data-integrity/v2-di-utils'\nimport { W3cV2JwtVerifiableCredential, W3cV2JwtVerifiablePresentation } from './jwt-vc'\nimport { W3cV2JwtCredentialService } from './jwt-vc/W3cV2JwtCredentialService'\nimport type {\n W3cV2PresentationCredentialEntry,\n W3cV2PresentationCredentialEntryResult,\n W3cV2VerifiableCredential,\n W3cV2VerifiablePresentation,\n W3cV2VerifyCredentialResult,\n W3cV2VerifyPresentationResult,\n} from './models'\nimport {\n ClaimFormat,\n decodeW3cV2VerifiablePresentation,\n W3cV2EnvelopedVerifiableCredential,\n W3cV2EnvelopedVerifiablePresentation,\n} from './models'\nimport { decodeW3cV2VerifiableCredential } from './models/credential/W3cV2VerifiableCredential'\nimport type { W3cV2Presentation } from './models/presentation/W3cV2Presentation'\nimport type { SingleValidationResult } from './models/W3cVerifyResult'\nimport { W3cV2CredentialRecord, W3cV2CredentialRepository } from './repository'\nimport { type ResolvedSigner } from './resolveSigner'\nimport {\n W3cV2SdJwtCredentialService,\n W3cV2SdJwtVerifiableCredential,\n W3cV2SdJwtVerifiablePresentation,\n} from './sd-jwt-vc'\nimport { getSignerForJwt } from './v2-jwt-utils'\nimport type {\n W3cV2DiSignCredentialOptions,\n W3cV2DiSignPresentationOptions,\n W3cV2DiVerifyCredentialOptions,\n W3cV2DiVerifyPresentationOptions,\n W3cV2JwtVerifyCredentialOptions,\n W3cV2JwtVerifyPresentationOptions,\n W3cV2SdJwtVerifyCredentialOptions,\n W3cV2SdJwtVerifyPresentationOptions,\n W3cV2SignCredentialOptions,\n W3cV2SignPresentationOptions,\n W3cV2StoreCredentialOptions,\n W3cV2VerifyCredentialOptions,\n W3cV2VerifyPresentationOptions,\n} from './W3cV2CredentialServiceOptions'\n\n@injectable()\nexport class W3cV2CredentialService {\n private w3cV2CredentialRepository: W3cV2CredentialRepository\n private w3cV2SdJwtCredentialService: W3cV2SdJwtCredentialService\n private w3cV2JwtCredentialService: W3cV2JwtCredentialService\n private w3cV2DataIntegrityCredentialService: W3cV2DataIntegrityCredentialService\n\n public constructor(\n w3cV2CredentialRepository: W3cV2CredentialRepository,\n w3cV2SdJwtCredentialService: W3cV2SdJwtCredentialService,\n w3cV2JwtCredentialService: W3cV2JwtCredentialService,\n w3cV2DataIntegrityCredentialService: W3cV2DataIntegrityCredentialService\n ) {\n this.w3cV2CredentialRepository = w3cV2CredentialRepository\n this.w3cV2SdJwtCredentialService = w3cV2SdJwtCredentialService\n this.w3cV2JwtCredentialService = w3cV2JwtCredentialService\n this.w3cV2DataIntegrityCredentialService = w3cV2DataIntegrityCredentialService\n }\n\n /**\n * Signs a credential\n *\n * @param credential the credential to be signed\n * @returns the signed credential\n */\n public async signCredential<Format extends ClaimFormat.JwtW3cVc | ClaimFormat.SdJwtW3cVc | ClaimFormat.DiVc>(\n agentContext: AgentContext,\n options: W3cV2SignCredentialOptions<Format>\n ): Promise<W3cV2VerifiableCredential<Format>> {\n if (options.format === ClaimFormat.JwtW3cVc) {\n const signed = await this.w3cV2JwtCredentialService.signCredential(agentContext, options)\n return signed as W3cV2VerifiableCredential<Format>\n }\n if (options.format === ClaimFormat.SdJwtW3cVc) {\n const signed = await this.w3cV2SdJwtCredentialService.signCredential(agentContext, options)\n return signed as W3cV2VerifiableCredential<Format>\n }\n if (options.format === ClaimFormat.DiVc) {\n const signed = await this.w3cV2DataIntegrityCredentialService.signCredential(\n agentContext,\n options as W3cV2DiSignCredentialOptions\n )\n return signed as W3cV2VerifiableCredential<Format>\n }\n throw new CredoError(`Unsupported format in options. Format must be either 'vc+jwt', 'vc+sd-jwt', or 'di_vc'`)\n }\n\n /**\n * Verifies the signature(s) of a credential\n */\n public async verifyCredential(\n agentContext: AgentContext,\n options: W3cV2VerifyCredentialOptions\n ): Promise<W3cV2VerifyCredentialResult> {\n const credential =\n typeof options.credential === 'string' ? decodeW3cV2VerifiableCredential(options.credential) : options.credential\n\n if (credential instanceof W3cV2JwtVerifiableCredential) {\n return this.w3cV2JwtCredentialService.verifyCredential(agentContext, {\n ...options,\n credential,\n } as W3cV2JwtVerifyCredentialOptions)\n }\n\n if (credential instanceof W3cV2SdJwtVerifiableCredential) {\n return this.w3cV2SdJwtCredentialService.verifyCredential(agentContext, {\n ...options,\n credential,\n } as W3cV2SdJwtVerifyCredentialOptions)\n }\n\n if (credential instanceof W3cV2DataIntegrityVerifiableCredential) {\n return this.w3cV2DataIntegrityCredentialService.verifyCredential(agentContext, {\n ...options,\n credential,\n } as W3cV2DiVerifyCredentialOptions)\n }\n\n throw new CredoError(\n 'Unsupported credential type in options. Credential must be either a W3cV2JwtVerifiableCredential, a W3cV2SdJwtVerifiableCredential, or a W3cV2DataIntegrityVerifiableCredential'\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<Format extends ClaimFormat.JwtW3cVp | ClaimFormat.SdJwtW3cVp | ClaimFormat.DiVp>(\n agentContext: AgentContext,\n options: W3cV2SignPresentationOptions<Format>\n ): Promise<W3cV2VerifiablePresentation<Format>> {\n if (options.format === ClaimFormat.JwtW3cVp) {\n const signed = await this.w3cV2JwtCredentialService.signPresentation(agentContext, options)\n return signed as W3cV2VerifiablePresentation<Format>\n }\n if (options.format === ClaimFormat.SdJwtW3cVp) {\n const signed = await this.w3cV2SdJwtCredentialService.signPresentation(agentContext, options)\n return signed as W3cV2VerifiablePresentation<Format>\n }\n if (options.format === ClaimFormat.DiVp) {\n const signed = await this.w3cV2DataIntegrityCredentialService.signPresentation(\n agentContext,\n options as W3cV2DiSignPresentationOptions\n )\n return signed as W3cV2VerifiablePresentation<Format>\n }\n throw new CredoError(`Unsupported format in options. Format must be either 'vp+jwt', 'vp+sd-jwt', or 'di_vp'`)\n }\n\n /**\n * Verifies a W3C V2 verifiable presentation and each enclosed credential entry.\n *\n * Flow:\n * 1. Verifies the outer VP using the format-specific service (`vp+jwt` or `vp+sd-jwt`).\n * 2. Derives the presenter identifier (holder id, or JWT verification method controller fallback).\n * 3. Recursively walks enclosed entries and verifies each credential entry with the matching\n * credential verifier (`vc+jwt` or `vc+sd-jwt`) based on the actual enclosed format.\n * 4. Adds `credentialSubjectAuthentication` validation to each credential result by checking\n * whether the authenticated presenter matches at least one credentialSubject id.\n *\n * Current support and constraints:\n * - Compact string presentations are accepted for `vp+jwt` and `vp+sd-jwt` and normalized\n * to typed presentation instances before routing.\n * - `di_vp` routes through the DI credential service for outer-VP verification.\n * - `di_vc` entries route through the DI credential service for entry verification.\n * - Nested VP entries are treated as invalid. VC 2.0 verifiable presentations support VC entries,\n * not VP-within-VP entries.\n *\n * Return semantics:\n * - `presentation` contains the outer VP verification result.\n * - `credentialEntries` contains one result per traversed credential entry, including unsupported\n * entries as invalid results.\n * - Top-level `isValid` is true only if the outer VP and all credential entry validations are valid.\n *\n * @param agentContext The framework agent context used for resolution and cryptographic checks.\n * @param options Verification input containing the presentation to verify.\n * @returns Aggregated presentation and credential-entry verification result.\n */\n public async verifyPresentation(\n agentContext: AgentContext,\n options: W3cV2VerifyPresentationOptions\n ): Promise<W3cV2VerifyPresentationResult> {\n const presentation =\n typeof options.presentation === 'string'\n ? decodeW3cV2VerifiablePresentation(options.presentation)\n : options.presentation\n\n const validationResults: W3cV2VerifyPresentationResult = {\n isValid: false,\n presentation: {\n isValid: false,\n validations: {},\n },\n credentialEntries: [],\n }\n\n let entries: W3cV2PresentationCredentialEntry[] = []\n let signer: ResolvedSigner\n\n // Phase 1: verify the outer secured VP envelope and derive the authenticated presenter.\n if (presentation instanceof W3cV2JwtVerifiablePresentation) {\n const presentationResult = await this.w3cV2JwtCredentialService.verifyPresentation(agentContext, {\n ...options,\n presentation,\n } as W3cV2JwtVerifyPresentationOptions)\n validationResults.presentation = presentationResult.presentation\n\n if (!presentationResult.presentation.isValid) {\n validationResults.isValid = false\n validationResults.error = presentationResult.error\n return validationResults\n }\n\n try {\n signer = await getSignerForJwt(agentContext, presentation, ['authentication'])\n } catch (error) {\n validationResults.isValid = false\n validationResults.error = error\n return validationResults\n }\n entries = this.extractCredentialEntriesFromPresentation(presentation)\n } else if (presentation instanceof W3cV2SdJwtVerifiablePresentation) {\n const presentationResult = await this.w3cV2SdJwtCredentialService.verifyPresentation(agentContext, {\n ...options,\n presentation,\n } as W3cV2SdJwtVerifyPresentationOptions)\n validationResults.presentation = presentationResult.presentation\n\n if (!presentationResult.presentation.isValid) {\n validationResults.isValid = false\n validationResults.error = presentationResult.error\n return validationResults\n }\n\n try {\n signer = await getSignerForJwt(agentContext, presentation, ['authentication'])\n } catch (error) {\n validationResults.isValid = false\n validationResults.error = error\n return validationResults\n }\n entries = this.extractCredentialEntriesFromPresentation(presentation)\n } else if (presentation instanceof W3cV2DataIntegrityVerifiablePresentation) {\n const presentationResult = await this.w3cV2DataIntegrityCredentialService.verifyPresentation(agentContext, {\n ...options,\n presentation,\n } as W3cV2DiVerifyPresentationOptions)\n validationResults.presentation = presentationResult.presentation\n\n if (!presentationResult.presentation.isValid) {\n validationResults.isValid = false\n validationResults.error = presentationResult.error\n return validationResults\n }\n\n try {\n // Without a holder there is nothing to disambiguate a proof set against, so an ambiguous\n // proof set is rejected rather than guessed at.\n signer = await resolveDataIntegritySigner(\n agentContext,\n presentation.securedPresentation,\n 'authentication',\n presentation.resolvedPresentation.holderId\n )\n } catch (error) {\n validationResults.isValid = false\n validationResults.error = error\n return validationResults\n }\n\n entries = this.extractCredentialEntriesFromPresentation(presentation)\n } else {\n throw new CredoError(\n 'Unsupported credential type in options. Presentation must be either a W3cV2JwtVerifiablePresentation, a W3cV2SdJwtVerifiablePresentation, or a W3cV2DataIntegrityVerifiablePresentation'\n )\n }\n\n // Phase 2: walk enclosed credential entries and verify recursively by entry format.\n validationResults.credentialEntries = (\n await Promise.all(\n entries.map((entry) =>\n this.verifyPresentationEntry(agentContext, entry, signer, options.trustedIssuers, {\n nonce: options.challenge,\n audience: options.domain,\n })\n )\n )\n ).flat()\n\n validationResults.isValid =\n validationResults.presentation.isValid && validationResults.credentialEntries.every((entry) => entry.isValid)\n\n return validationResults\n }\n\n private async verifyPresentationEntry(\n agentContext: AgentContext,\n entry: W3cV2PresentationCredentialEntry,\n signer: ResolvedSigner,\n trustedIssuers: TrustedIssuerDid[] | GetTrustedIssuersForCredential | undefined,\n presentationBinding: { nonce: string; audience?: string }\n ): Promise<W3cV2PresentationCredentialEntryResult[]> {\n if (entry instanceof W3cV2DataIntegrityVerifiablePresentation) {\n return [\n this.createInvalidCredentialEntryResult(\n new CredoError('Nested verifiable presentation entries are not supported in VC 2.0 presentations.')\n ),\n ]\n }\n\n if (entry instanceof W3cV2DataIntegrityVerifiableCredential) {\n const credentialResult = await this.w3cV2DataIntegrityCredentialService.verifyCredential(agentContext, {\n credential: entry,\n trustedIssuers,\n } as W3cV2DiVerifyCredentialOptions)\n\n return [\n this.mergeHolderValidations(credentialResult, signer, entry.resolvedCredential?.credentialSubjectIds ?? [], {\n isValid: true,\n }),\n ]\n }\n\n if (entry instanceof W3cV2EnvelopedVerifiablePresentation) {\n return [\n this.createInvalidCredentialEntryResult(\n new CredoError('Nested verifiable presentation entries are not supported in VC 2.0 presentations.')\n ),\n ]\n }\n\n if (!(entry instanceof W3cV2EnvelopedVerifiableCredential)) {\n return [\n this.createInvalidCredentialEntryResult(new CredoError('Unsupported credential entry type in presentation.')),\n ]\n }\n\n const enclosed = entry.envelopedCredential\n let credentialResult: W3cV2VerifyCredentialResult\n let claims: Record<string, unknown>\n\n if (enclosed instanceof W3cV2JwtVerifiableCredential) {\n credentialResult = await this.w3cV2JwtCredentialService.verifyCredential(agentContext, {\n credential: enclosed,\n trustedIssuers,\n } as W3cV2JwtVerifyCredentialOptions)\n claims = enclosed.jwt.payload.toJson()\n } else if (enclosed instanceof W3cV2SdJwtVerifiableCredential) {\n // The presentation proves possession of the key. A KB-JWT is optional, but must match the presentation.\n const { nonce, audience } = presentationBinding\n if (enclosed.sdJwt.kbJwt && !audience) {\n return [\n this.createInvalidCredentialEntryResult(\n new CredoError('Credential has a KB-JWT, but no domain is provided to verify its audience')\n ),\n ]\n }\n\n credentialResult = await this.w3cV2SdJwtCredentialService.verifyCredential(agentContext, {\n credential: enclosed,\n trustedIssuers,\n keyBinding: enclosed.sdJwt.kbJwt && audience ? { nonce, audience } : undefined,\n } as W3cV2SdJwtVerifyCredentialOptions)\n claims = enclosed.sdJwt.prettyClaims\n } else {\n return [\n this.createInvalidCredentialEntryResult(\n new CredoError(\n `Credential entry uses '${this.getClaimFormat(enclosed) ?? 'an unsupported enclosed credential format'}'.`\n )\n ),\n ]\n }\n\n return [\n this.mergeHolderValidations(\n credentialResult,\n signer,\n entry.resolvedCredential.credentialSubjectIds,\n await this.verifyHolderBinding(agentContext, claims, signer)\n ),\n ]\n }\n\n /**\n * A credential bound to a key with `cnf` must be presented with that key.\n */\n private async verifyHolderBinding(\n agentContext: AgentContext,\n claims: Record<string, unknown>,\n signer: ResolvedSigner\n ): Promise<SingleValidationResult> {\n try {\n const holderBinding = parseHolderBindingFromCredential(claims)\n if (!holderBinding) return { isValid: true }\n\n // The presentation signer is resolved under `authentication`, so the holder key must be too\n const { publicJwk } = await extractKeyFromHolderBinding(agentContext, holderBinding, {\n didPurposes: ['authentication'],\n })\n if (publicJwk.equals(getPublicJwkFromVerificationMethod(signer.verificationMethod))) return { isValid: true }\n\n return {\n isValid: false,\n error: new CredoError(\n `Credential is bound to a different key than verification method ${signer.verificationMethod.id} that signed the presentation`\n ),\n }\n } catch (error) {\n return { isValid: false, error }\n }\n }\n\n private extractCredentialEntriesFromPresentation(\n presentation:\n | W3cV2JwtVerifiablePresentation\n | W3cV2SdJwtVerifiablePresentation\n | W3cV2DataIntegrityVerifiablePresentation\n ): W3cV2PresentationCredentialEntry[] {\n return this.extractCredentialEntriesFromResolvedPresentation(presentation.resolvedPresentation)\n }\n\n private extractCredentialEntriesFromResolvedPresentation(\n resolvedPresentation: Pick<W3cV2Presentation, 'verifiableCredential'> | W3cV2DataIntegrityResolvedPresentation\n ): W3cV2PresentationCredentialEntry[] {\n return asArray(resolvedPresentation.verifiableCredential) as W3cV2PresentationCredentialEntry[]\n }\n\n private createInvalidCredentialEntryResult(error: Error): W3cV2PresentationCredentialEntryResult {\n return {\n isValid: false,\n error,\n validations: {},\n }\n }\n\n private getClaimFormat(value: unknown): string | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined\n\n const candidate = value as { claimFormat?: unknown }\n return typeof candidate.claimFormat === 'string' ? candidate.claimFormat : undefined\n }\n\n private mergeHolderValidations(\n credentialResult: W3cV2VerifyCredentialResult,\n signer: ResolvedSigner,\n credentialSubjectIds: string[],\n holderBinding: SingleValidationResult\n ) {\n const presentationAuthenticatesCredentialSubject = credentialSubjectIds.some(\n (subjectId) => signer.signer === subjectId\n )\n\n const credentialSubjectAuthentication =\n credentialSubjectIds.length > 0 && !presentationAuthenticatesCredentialSubject\n ? {\n isValid: false,\n error: new CredoError(\n 'Credential has one or more credentialSubject ids, but presentation does not authenticate credential subject'\n ),\n }\n : {\n isValid: true,\n }\n\n return {\n ...credentialResult,\n isValid: credentialResult.isValid && credentialSubjectAuthentication.isValid && holderBinding.isValid,\n validations: {\n ...credentialResult.validations,\n credentialSubjectAuthentication,\n holderBinding,\n },\n }\n }\n\n /**\n * Writes a credential to storage\n *\n * @param record the credential to be stored\n * @returns the credential record that was written to storage\n */\n public async storeCredential(\n agentContext: AgentContext,\n options: W3cV2StoreCredentialOptions\n ): Promise<W3cV2CredentialRecord> {\n // Store the w3cV2 credential record\n await this.w3cV2CredentialRepository.save(agentContext, options.record)\n\n return options.record\n }\n\n public async removeCredentialRecord(agentContext: AgentContext, id: string) {\n await this.w3cV2CredentialRepository.deleteById(agentContext, id)\n }\n\n public async getAllCredentialRecords(agentContext: AgentContext): Promise<W3cV2CredentialRecord[]> {\n return await this.w3cV2CredentialRepository.getAll(agentContext)\n }\n\n public async getCredentialRecordById(agentContext: AgentContext, id: string): Promise<W3cV2CredentialRecord> {\n return await this.w3cV2CredentialRepository.getById(agentContext, id)\n }\n\n public async findCredentialsByQuery(\n agentContext: AgentContext,\n query: Query<W3cV2CredentialRecord>,\n queryOptions?: QueryOptions\n ): Promise<W3cV2VerifiableCredential[]> {\n const result = await this.w3cV2CredentialRepository.findByQuery(agentContext, query, queryOptions)\n return result.map((record) => record.firstCredential)\n }\n\n public async findCredentialRecordByQuery(\n agentContext: AgentContext,\n query: Query<W3cV2CredentialRecord>\n ): Promise<W3cV2VerifiableCredential | undefined> {\n const result = await this.w3cV2CredentialRepository.findSingleByQuery(agentContext, query)\n return result?.firstCredential\n }\n}\n"],"mappings":"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"}
@@ -17,7 +17,7 @@ import "./repository/index.mjs";
17
17
  import "./sd-jwt-vc/index.mjs";
18
18
  import "./jwt-vc/index.mjs";
19
19
  import "./data-integrity/index.mjs";
20
- import { TrustedIssuerDid } from "../../agent/TrustedIssuersForVerification.mjs";
20
+ import { GetTrustedIssuersForCredential, TrustedIssuerDid } from "../../agent/TrustedIssuersForVerification.mjs";
21
21
  import "../../crypto/index.mjs";
22
22
  import "../kms/index.mjs";
23
23
  //#region src/modules/vc/W3cV2CredentialServiceOptions.d.ts
@@ -100,12 +100,20 @@ interface W3cV2VerifyCredentialOptionsBase<Credential = unknown> {
100
100
  */
101
101
  verifyCredentialStatus?: boolean;
102
102
  /**
103
- * Trusted issuers for the verification.
103
+ * Trusted issuers for the verification, or a callback that resolves them for each credential.
104
104
  */
105
- trustedIssuers?: TrustedIssuerDid[];
105
+ trustedIssuers?: TrustedIssuerDid[] | GetTrustedIssuersForCredential;
106
106
  }
107
107
  export interface W3cV2JwtVerifyCredentialOptions extends W3cV2VerifyCredentialOptionsBase<W3cV2JwtVerifiableCredential | string> {}
108
- export interface W3cV2SdJwtVerifyCredentialOptions extends W3cV2VerifyCredentialOptionsBase<W3cV2SdJwtVerifiableCredential | string> {}
108
+ export interface W3cV2SdJwtVerifyCredentialOptions extends W3cV2VerifyCredentialOptionsBase<W3cV2SdJwtVerifiableCredential | string> {
109
+ /**
110
+ * Requires a KB-JWT with this `nonce`, and with this `aud` when `audience` is set.
111
+ */
112
+ keyBinding?: {
113
+ nonce: string;
114
+ audience: string | string[];
115
+ };
116
+ }
109
117
  interface W3cV2SignPresentationOptionsBase<Format extends ClaimFormat = ClaimFormat> {
110
118
  /**
111
119
  * The format of the presentation to be signed.
@@ -154,9 +162,9 @@ interface W3cV2VerifyPresentationOptionsBase<Presentation = unknown> {
154
162
  */
155
163
  domain?: string;
156
164
  /**
157
- * Trusted issuers for the verification.
165
+ * Trusted issuers for the verification, or a callback that resolves them for each credential.
158
166
  */
159
- trustedIssuers?: TrustedIssuerDid[];
167
+ trustedIssuers?: TrustedIssuerDid[] | GetTrustedIssuersForCredential;
160
168
  }
161
169
  export interface W3cV2JwtVerifyPresentationOptions extends W3cV2VerifyPresentationOptionsBase<W3cV2JwtVerifiablePresentation | string> {}
162
170
  export interface W3cV2SdJwtVerifyPresentationOptions extends W3cV2VerifyPresentationOptionsBase<W3cV2SdJwtVerifiablePresentation | string> {}
@@ -1 +1 @@
1
- {"version":3,"file":"W3cV2CredentialServiceOptions.d.mts","names":[],"sources":["../../../src/modules/vc/W3cV2CredentialServiceOptions.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;KAUK;GACF,YAAY,WAAW;GACvB,YAAY,aAAa;GACzB,YAAY,OAAO;;KAGjB;GACF,YAAY,WAAW;GACvB,YAAY,aAAa;GACzB,YAAY,OAAO;;KAGjB;GACF,YAAY,WAAW;GACvB,YAAY,aAAa;GACzB,YAAY,OAAO;;YAGV,2BACV,qBAAqB,8DACnB,qBAAqB,qCACrB,mCAAmC,UACnC,yCAAyC;YAEjC,6BACV,qBAAqB,gEACnB,qBAAqB,uCACrB,qCAAqC,UACrC,2CAA2C;YAEnC,6BACV,qBAAqB,gEACnB,qBAAqB,uCACrB,qCAAqC,UACrC,2CAA2C;YAEnC,iCACR,oCACA,sCACA;UAEM,+BAA+B,eAAe,cAAc;;;;;;EAMpE,QAAQ;;;;EAKR,YAAY;;;;;;EAOZ;;iBAGe,sCAAsC,+BAA+B,YAAY;;;;EAIhG,KAAK;;;;;EAML,SAAS;;iBAGM,wCAAwC,+BAA+B,YAAY;;;;EAIlG,KAAK;;;;;;EAOL,mBAAmB,QAAQ;;;;;EAM3B,SAAS;;;;;EAMT,kBAAkB;;UAGV,iCAAiC;EACzC,YAAY;;;;;;EAOZ;;;;EAKA,iBAAiB;;iBAGF,wCACP,iCAAiC;iBAE1B,0CACP,iCAAiC;UAEjC,iCAAiC,eAAe,cAAc;;;;;;EAMtE,QAAQ;;;;EAKR,cAAc;;;;EAKd;;;;EAKA;;iBAGe,wCAAwC,iCAAiC,YAAY;iBAErF,0CAA0C,iCAAiC,YAAY;;;;;;EAMtG,mBAAmB,QAAQ;;;;;EAM3B,kBAAkB;;UAGV,mCAAmC;;;;EAI3C,cAAc;;;;EAKd;;;;EAKA;;;;EAKA,iBAAiB;;iBAGF,0CACP,mCAAmC;iBAE5B,4CACP,mCAAmC;iBAE5B;EACf,QAAQ;;iBAGO;EACf,YAAY;;;;EAKZ,oBAAoB;;;;;iBAML,qCAAqC,+BAA+B,YAAY;;;;EAI/F;;;;;iBAMe,uCACP,iCAAiC;;;;iBAK1B,uCAAuC,iCAAiC,YAAY;;;;;;EAMnG;;;;EAKA;;;;;iBAMe,yCACP,mCAAmC"}
1
+ {"version":3,"file":"W3cV2CredentialServiceOptions.d.mts","names":[],"sources":["../../../src/modules/vc/W3cV2CredentialServiceOptions.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;KAUK;GACF,YAAY,WAAW;GACvB,YAAY,aAAa;GACzB,YAAY,OAAO;;KAGjB;GACF,YAAY,WAAW;GACvB,YAAY,aAAa;GACzB,YAAY,OAAO;;KAGjB;GACF,YAAY,WAAW;GACvB,YAAY,aAAa;GACzB,YAAY,OAAO;;YAGV,2BACV,qBAAqB,8DACnB,qBAAqB,qCACrB,mCAAmC,UACnC,yCAAyC;YAEjC,6BACV,qBAAqB,gEACnB,qBAAqB,uCACrB,qCAAqC,UACrC,2CAA2C;YAEnC,6BACV,qBAAqB,gEACnB,qBAAqB,uCACrB,qCAAqC,UACrC,2CAA2C;YAEnC,iCACR,oCACA,sCACA;UAEM,+BAA+B,eAAe,cAAc;;;;;;EAMpE,QAAQ;;;;EAKR,YAAY;;;;;;EAOZ;;iBAGe,sCAAsC,+BAA+B,YAAY;;;;EAIhG,KAAK;;;;;EAML,SAAS;;iBAGM,wCAAwC,+BAA+B,YAAY;;;;EAIlG,KAAK;;;;;;EAOL,mBAAmB,QAAQ;;;;;EAM3B,SAAS;;;;;EAMT,kBAAkB;;UAGV,iCAAiC;EACzC,YAAY;;;;;;EAOZ;;;;EAKA,iBAAiB,qBAAqB;;iBAGvB,wCACP,iCAAiC;iBAE1B,0CACP,iCAAiC;;;;EAIzC;IACE;IACA;;;UAIM,iCAAiC,eAAe,cAAc;;;;;;EAMtE,QAAQ;;;;EAKR,cAAc;;;;EAKd;;;;EAKA;;iBAGe,wCAAwC,iCAAiC,YAAY;iBAErF,0CAA0C,iCAAiC,YAAY;;;;;;EAMtG,mBAAmB,QAAQ;;;;;EAM3B,kBAAkB;;UAGV,mCAAmC;;;;EAI3C,cAAc;;;;EAKd;;;;EAKA;;;;EAKA,iBAAiB,qBAAqB;;iBAGvB,0CACP,mCAAmC;iBAE5B,4CACP,mCAAmC;iBAE5B;EACf,QAAQ;;iBAGO;EACf,YAAY;;;;EAKZ,oBAAoB;;;;;iBAML,qCAAqC,+BAA+B,YAAY;;;;EAI/F;;;;;iBAMe,uCACP,iCAAiC;;;;iBAK1B,uCAAuC,iCAAiC,YAAY;;;;;;EAMnG;;;;EAKA;;;;;iBAMe,yCACP,mCAAmC"}
@@ -17,24 +17,6 @@ export declare class W3cV2DataIntegrityCredentialService {
17
17
  verifyCredential(agentContext: AgentContext, options: W3cV2DiVerifyCredentialOptions): Promise<W3cV2VerifyCredentialResult>;
18
18
  signPresentation(agentContext: AgentContext, options: W3cV2DiSignPresentationOptions): Promise<W3cV2VerifiablePresentation<ClaimFormat.DiVp>>;
19
19
  verifyPresentation(agentContext: AgentContext, options: W3cV2DiVerifyPresentationOptions): Promise<W3cV2VerifyPresentationResult>;
20
- /**
21
- * Checks that a secured document was signed by the identity it names as responsible for it —
22
- * the `issuer` of a credential, or the `holder` of a presentation.
23
- *
24
- * Mirrors the equivalent checks in the JWT and SD-JWT services — though those compare key
25
- * fingerprints for the issuer, whereas Data Integrity proofs name a verification method, so the
26
- * comparison here is by controller for both roles. It implements the association described in
27
- * VC-DATA-INTEGRITY §"Relationship to Verifiable Credentials": that the `controller` of the
28
- * proof's verification method matches the identifier used for the `issuer` or `holder`, and that
29
- * the verification method is expressed under a verification relationship acceptable for the
30
- * proof's purpose. The latter is enforced by dereferencing the key with `purpose`.
31
- *
32
- * Verifying the proof only establishes that *someone* signed; without this comparison a document
33
- * could name one party and be signed by an unrelated one.
34
- *
35
- * @param expectedSigner the `issuer` or `holder`. `Holder` is optional in
36
- * VCDM 2.0 so when undefined there is no claim to contradict, so the validation passes.
37
- */
38
20
  private verifySignerIsExpectedParty;
39
21
  private invalidResult;
40
22
  private invalidValidation;
@@ -1 +1 @@
1
- {"version":3,"file":"W3cV2DataIntegrityCredentialService.d.mts","names":[],"sources":["../../../../src/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.ts"],"mappings":";;;;;;;;;;;qBA8Ba;UACH;UACA;EAGN,YAAA,2BAA2B,8BAC3B,kBAAkB;EAMP,eACX,cAAc,cACd,SAAS,+BACR,QAAQ,0BAA0B,YAAY;EAgCpC,iBACX,cAAc,cACd,SAAS,iCACR,QAAQ;EA+CE,iBACX,cAAc,cACd,SAAS,iCACR,QAAQ,4BAA4B,YAAY;EAuCtC,mBACX,cAAc,cACd,SAAS,mCACR,QAAQ;;;;;;;;;;;;;;;;;;;UAiEG;UAmCN;UAoBA;UAOA"}
1
+ {"version":3,"file":"W3cV2DataIntegrityCredentialService.d.mts","names":[],"sources":["../../../../src/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.ts"],"mappings":";;;;;;;;;;;qBAgCa;UACH;UACA;EAGN,YAAA,2BAA2B,8BAC3B,kBAAkB;EAMP,eACX,cAAc,cACd,SAAS,+BACR,QAAQ,0BAA0B,YAAY;EAgCpC,iBACX,cAAc,cACd,SAAS,iCACR,QAAQ;EA6DE,iBACX,cAAc,cACd,SAAS,iCACR,QAAQ,4BAA4B,YAAY;EAuCtC,mBACX,cAAc,cACd,SAAS,mCACR,QAAQ;UA8CG;UAmBN;UAoBA;UAOA"}
@@ -7,7 +7,9 @@ import { injectable } from "../../../plugins/index.mjs";
7
7
  import __decorateMetadata from "../../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.mjs";
8
8
  import __decorate from "../../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.mjs";
9
9
  import { CREDENTIALS_CONTEXT_V2_URL } from "../constants.mjs";
10
+ import { TrustedIssuerContext } from "../../../agent/TrustedIssuerContext.mjs";
10
11
  import { validateVc2ContextBaseline, validateVc2CredentialStatus } from "../validators.mjs";
12
+ import { validateSignerIsExpectedParty } from "../resolveSigner.mjs";
11
13
  import { W3cV2Credential } from "../models/credential/W3cV2Credential.mjs";
12
14
  import { W3cV2DataIntegrityVerifiableCredential } from "./W3cV2DataIntegrityVerifiableCredential.mjs";
13
15
  import { W3cV2DataIntegrityVerifiablePresentation } from "./W3cV2DataIntegrityVerifiablePresentation.mjs";
@@ -16,7 +18,7 @@ import { createW3cDataIntegrityCredoError } from "../../w3c-di/W3cDataIntegrityE
16
18
  import { W3cDataIntegrityProofService } from "../../w3c-di/W3cDataIntegrityProofService.mjs";
17
19
  import "../../w3c-di/internal.mjs";
18
20
  import { W3cV2DataIntegrityContextValidator } from "./W3cV2DataIntegrityContextValidator.mjs";
19
- import { getVerificationMethodForDataIntegrityProof } from "./v2-di-utils.mjs";
21
+ import { resolveDataIntegritySigner } from "./v2-di-utils.mjs";
20
22
  //#region src/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.ts
21
23
  let W3cV2DataIntegrityCredentialService = class W3cV2DataIntegrityCredentialService {
22
24
  constructor(dataIntegrityProofService, contextValidator) {
@@ -52,15 +54,34 @@ let W3cV2DataIntegrityCredentialService = class W3cV2DataIntegrityCredentialServ
52
54
  credentialFormat: "DI",
53
55
  verifyCredentialStatus: options.verifyCredentialStatus
54
56
  });
55
- const issuerIsSigner = await this.verifySignerIsExpectedParty(agentContext, securedCredential, "assertionMethod", options.credential.resolvedCredential.issuerId, (verificationMethodId, issuerId) => `Credential is signed using verification method ${verificationMethodId}, while the issuer of the credential is '${issuerId}'`);
57
+ const { validation: issuerIsSigner, signer: issuer } = await this.verifySignerIsExpectedParty(agentContext, securedCredential, "assertionMethod", options.credential.resolvedCredential.issuerId, "issuer");
58
+ const validations = {
59
+ dataModel: { isValid: true },
60
+ signature: { isValid: true },
61
+ credentialStatus,
62
+ issuerIsSigner
63
+ };
64
+ if (issuer && issuerIsSigner.isValid) try {
65
+ await TrustedIssuerContext.ensureTrustedCredentialSigner(agentContext, {
66
+ signer: {
67
+ method: "did",
68
+ didUrl: issuer.verificationMethod.id
69
+ },
70
+ verification: {
71
+ type: "credential",
72
+ credential: options.credential
73
+ }
74
+ }, options.trustedIssuers);
75
+ } catch (error) {
76
+ return {
77
+ isValid: false,
78
+ validations,
79
+ error
80
+ };
81
+ }
56
82
  return {
57
83
  isValid: credentialStatus.isValid && issuerIsSigner.isValid,
58
- validations: {
59
- dataModel: { isValid: true },
60
- signature: { isValid: true },
61
- credentialStatus,
62
- issuerIsSigner
63
- }
84
+ validations
64
85
  };
65
86
  }
66
87
  async signPresentation(agentContext, options) {
@@ -101,7 +122,7 @@ let W3cV2DataIntegrityCredentialService = class W3cV2DataIntegrityCredentialServ
101
122
  if (!verificationResult.verified) return this.invalidResult(verificationResult.errors, "presentation");
102
123
  const presentationContextResult = await this.contextValidator.validate(agentContext, securedPresentation);
103
124
  if (!presentationContextResult.validated) return this.invalidResult(presentationContextResult.errors, "presentation");
104
- const holderIsSigner = await this.verifySignerIsExpectedParty(agentContext, options.presentation.securedPresentation, "authentication", options.presentation.resolvedPresentation.holderId, (verificationMethodId, holderId) => `Presentation is signed using verification method ${verificationMethodId}, while the holder of the presentation is '${holderId}'`);
125
+ const { validation: holderIsSigner } = await this.verifySignerIsExpectedParty(agentContext, options.presentation.securedPresentation, "authentication", options.presentation.resolvedPresentation.holderId, "holder");
105
126
  return {
106
127
  isValid: holderIsSigner.isValid,
107
128
  presentation: {
@@ -115,38 +136,19 @@ let W3cV2DataIntegrityCredentialService = class W3cV2DataIntegrityCredentialServ
115
136
  credentialEntries: []
116
137
  };
117
138
  }
118
- /**
119
- * Checks that a secured document was signed by the identity it names as responsible for it —
120
- * the `issuer` of a credential, or the `holder` of a presentation.
121
- *
122
- * Mirrors the equivalent checks in the JWT and SD-JWT services — though those compare key
123
- * fingerprints for the issuer, whereas Data Integrity proofs name a verification method, so the
124
- * comparison here is by controller for both roles. It implements the association described in
125
- * VC-DATA-INTEGRITY §"Relationship to Verifiable Credentials": that the `controller` of the
126
- * proof's verification method matches the identifier used for the `issuer` or `holder`, and that
127
- * the verification method is expressed under a verification relationship acceptable for the
128
- * proof's purpose. The latter is enforced by dereferencing the key with `purpose`.
129
- *
130
- * Verifying the proof only establishes that *someone* signed; without this comparison a document
131
- * could name one party and be signed by an unrelated one.
132
- *
133
- * @param expectedSigner the `issuer` or `holder`. `Holder` is optional in
134
- * VCDM 2.0 so when undefined there is no claim to contradict, so the validation passes.
135
- */
136
- async verifySignerIsExpectedParty(agentContext, securedDocument, purpose, expectedSigner, describeMismatch) {
137
- if (!expectedSigner) return { isValid: true };
139
+ async verifySignerIsExpectedParty(agentContext, securedDocument, purpose, expectedSigner, role) {
140
+ if (!expectedSigner) return { validation: { isValid: true } };
138
141
  try {
139
- const verificationMethod = await getVerificationMethodForDataIntegrityProof(agentContext, securedDocument, purpose, expectedSigner);
140
- if (verificationMethod.controller !== expectedSigner) return {
141
- isValid: false,
142
- error: new CredoError(describeMismatch(verificationMethod.id, expectedSigner))
142
+ const signer = await resolveDataIntegritySigner(agentContext, securedDocument, purpose, expectedSigner);
143
+ return {
144
+ validation: validateSignerIsExpectedParty(signer, expectedSigner, role),
145
+ signer
143
146
  };
144
- return { isValid: true };
145
147
  } catch (error) {
146
- return {
148
+ return { validation: {
147
149
  isValid: false,
148
150
  error
149
- };
151
+ } };
150
152
  }
151
153
  }
152
154
  invalidResult(errors, target) {
@@ -1 +1 @@
1
- {"version":3,"file":"W3cV2DataIntegrityCredentialService.mjs","names":["createDataIntegrityCredoError"],"sources":["../../../../src/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.ts"],"sourcesContent":["import type { AgentContext } from '../../../agent/context'\nimport { CredoError } from '../../../error'\nimport { injectable } from '../../../plugins'\nimport { JsonTransformer, MessageValidator } from '../../../utils'\nimport {\n createW3cDataIntegrityCredoError as createDataIntegrityCredoError,\n type W3cDataIntegrityIssueList as DataIntegrityIssueList,\n W3cDataIntegrityProofService as DataIntegrityProofService,\n} from '../../w3c-di/internal'\nimport { CREDENTIALS_CONTEXT_V2_URL } from '../constants'\nimport { ClaimFormat } from '../models/ClaimFormat'\nimport { W3cV2Credential } from '../models/credential/W3cV2Credential'\nimport type { W3cV2VerifiableCredential } from '../models/credential/W3cV2VerifiableCredential'\nimport { W3cV2Presentation } from '../models/presentation/W3cV2Presentation'\nimport type { W3cV2VerifiablePresentation } from '../models/presentation/W3cV2VerifiablePresentation'\nimport type { W3cV2VerifyCredentialResult, W3cV2VerifyPresentationResult } from '../models/W3cV2VerifyResult'\nimport type { SingleValidationResult } from '../models/W3cVerifyResult'\nimport { validateVc2ContextBaseline, validateVc2CredentialStatus } from '../validators'\nimport type {\n W3cV2DiSignCredentialOptions,\n W3cV2DiSignPresentationOptions,\n W3cV2DiVerifyCredentialOptions,\n W3cV2DiVerifyPresentationOptions,\n} from '../W3cV2CredentialServiceOptions'\nimport { getVerificationMethodForDataIntegrityProof } from './v2-di-utils'\nimport { W3cV2DataIntegrityContextValidator } from './W3cV2DataIntegrityContextValidator'\nimport { W3cV2DataIntegrityVerifiableCredential } from './W3cV2DataIntegrityVerifiableCredential'\nimport { W3cV2DataIntegrityVerifiablePresentation } from './W3cV2DataIntegrityVerifiablePresentation'\n\n@injectable()\nexport class W3cV2DataIntegrityCredentialService {\n private dataIntegrityProofService: DataIntegrityProofService\n private contextValidator: W3cV2DataIntegrityContextValidator\n\n public constructor(\n dataIntegrityProofService: DataIntegrityProofService,\n contextValidator: W3cV2DataIntegrityContextValidator\n ) {\n this.dataIntegrityProofService = dataIntegrityProofService\n this.contextValidator = contextValidator\n }\n\n public async signCredential(\n agentContext: AgentContext,\n options: W3cV2DiSignCredentialOptions\n ): Promise<W3cV2VerifiableCredential<ClaimFormat.DiVc>> {\n const unsecuredCredential = JsonTransformer.toJSON(options.credential)\n if (unsecuredCredential['@context'] === undefined || unsecuredCredential['@context'] === null) {\n unsecuredCredential['@context'] = [CREDENTIALS_CONTEXT_V2_URL]\n }\n\n MessageValidator.validateSync(JsonTransformer.fromJSON(unsecuredCredential, W3cV2Credential, { validate: false }))\n\n const contextValidation = validateVc2ContextBaseline(unsecuredCredential['@context'])\n if (!contextValidation.isValid) {\n throw contextValidation.error ?? new CredoError('VC2 credential @context validation failed')\n }\n\n const proofResult = await this.dataIntegrityProofService.createProof(agentContext, {\n unsecuredDocument: unsecuredCredential,\n verificationMethod: options.verificationMethod,\n proofPurpose: 'assertionMethod',\n cryptosuite: options.cryptosuite,\n })\n\n if (!proofResult.created) {\n throw createDataIntegrityCredoError(proofResult.errors)\n }\n\n return new W3cV2DataIntegrityVerifiableCredential({\n securedCredential: {\n ...unsecuredCredential,\n proof: proofResult.proof,\n },\n })\n }\n\n public async verifyCredential(\n agentContext: AgentContext,\n options: W3cV2DiVerifyCredentialOptions\n ): Promise<W3cV2VerifyCredentialResult> {\n const securedCredential = options.credential.securedCredential\n const verificationResult = Array.isArray(securedCredential.proof)\n ? await this.dataIntegrityProofService.verifyProofSetAndChain(agentContext, securedCredential as never, {\n expectedProofPurpose: 'assertionMethod',\n })\n : await this.dataIntegrityProofService.verifyProof(agentContext, securedCredential as never, {\n expectedProofPurpose: 'assertionMethod',\n })\n\n if (!verificationResult.verified) {\n return this.invalidResult(verificationResult.errors, 'credential')\n }\n\n const contextResult = await this.contextValidator.validate(agentContext, securedCredential)\n if (!contextResult.validated) {\n return this.invalidResult(contextResult.errors as DataIntegrityIssueList, 'credential')\n }\n\n const credentialStatus = validateVc2CredentialStatus({\n credentialStatus: securedCredential.credentialStatus,\n credentialFormat: 'DI',\n verifyCredentialStatus: options.verifyCredentialStatus,\n })\n\n const issuerIsSigner = await this.verifySignerIsExpectedParty(\n agentContext,\n securedCredential,\n 'assertionMethod',\n options.credential.resolvedCredential.issuerId,\n (verificationMethodId, issuerId) =>\n `Credential is signed using verification method ${verificationMethodId}, while the issuer of the credential is '${issuerId}'`\n )\n\n const isValid = credentialStatus.isValid && issuerIsSigner.isValid\n\n return {\n isValid,\n validations: {\n dataModel: { isValid: true },\n signature: { isValid: true },\n credentialStatus,\n issuerIsSigner,\n },\n }\n }\n\n public async signPresentation(\n agentContext: AgentContext,\n options: W3cV2DiSignPresentationOptions\n ): Promise<W3cV2VerifiablePresentation<ClaimFormat.DiVp>> {\n const unsecuredPresentation = JsonTransformer.toJSON(options.presentation)\n if (unsecuredPresentation['@context'] === undefined || unsecuredPresentation['@context'] === null) {\n unsecuredPresentation['@context'] = [CREDENTIALS_CONTEXT_V2_URL]\n }\n\n MessageValidator.validateSync(\n JsonTransformer.fromJSON(unsecuredPresentation, W3cV2Presentation, { validate: false })\n )\n\n const contextValidation = validateVc2ContextBaseline(unsecuredPresentation['@context'])\n if (!contextValidation.isValid) {\n throw contextValidation.error ?? new CredoError('VC2 presentation @context validation failed')\n }\n\n const proofResult = await this.dataIntegrityProofService.createProof(agentContext, {\n unsecuredDocument: unsecuredPresentation,\n verificationMethod: options.verificationMethod,\n proofPurpose: 'authentication',\n cryptosuite: options.cryptosuite,\n challenge: options.challenge,\n domain: options.domain,\n })\n\n if (!proofResult.created) {\n throw createDataIntegrityCredoError(proofResult.errors)\n }\n\n const securedPresentation = {\n ...unsecuredPresentation,\n proof: proofResult.proof,\n }\n\n return new W3cV2DataIntegrityVerifiablePresentation({\n securedPresentation,\n resolvedPresentation: JsonTransformer.fromJSON(securedPresentation, W3cV2Presentation, { validate: false }),\n })\n }\n\n public async verifyPresentation(\n agentContext: AgentContext,\n options: W3cV2DiVerifyPresentationOptions\n ): Promise<W3cV2VerifyPresentationResult> {\n const securedPresentation = options.presentation.securedPresentation\n\n const verificationResult = Array.isArray(securedPresentation.proof)\n ? await this.dataIntegrityProofService.verifyProofSetAndChain(agentContext, securedPresentation as never, {\n expectedProofPurpose: 'authentication',\n challenge: options.challenge,\n domain: options.domain,\n })\n : await this.dataIntegrityProofService.verifyProof(agentContext, securedPresentation as never, {\n expectedProofPurpose: 'authentication',\n challenge: options.challenge,\n domain: options.domain,\n })\n\n if (!verificationResult.verified) {\n return this.invalidResult(verificationResult.errors, 'presentation')\n }\n\n const presentationContextResult = await this.contextValidator.validate(agentContext, securedPresentation)\n if (!presentationContextResult.validated) {\n return this.invalidResult(presentationContextResult.errors as DataIntegrityIssueList, 'presentation')\n }\n\n const holderIsSigner = await this.verifySignerIsExpectedParty(\n agentContext,\n options.presentation.securedPresentation,\n 'authentication',\n options.presentation.resolvedPresentation.holderId,\n (verificationMethodId, holderId) =>\n `Presentation is signed using verification method ${verificationMethodId}, while the holder of the presentation is '${holderId}'`\n )\n\n return {\n isValid: holderIsSigner.isValid,\n presentation: {\n isValid: holderIsSigner.isValid,\n validations: {\n dataModel: { isValid: true },\n holderIsSigner,\n presentationSignature: { isValid: true },\n },\n },\n credentialEntries: [],\n }\n }\n\n /**\n * Checks that a secured document was signed by the identity it names as responsible for it —\n * the `issuer` of a credential, or the `holder` of a presentation.\n *\n * Mirrors the equivalent checks in the JWT and SD-JWT services — though those compare key\n * fingerprints for the issuer, whereas Data Integrity proofs name a verification method, so the\n * comparison here is by controller for both roles. It implements the association described in\n * VC-DATA-INTEGRITY §\"Relationship to Verifiable Credentials\": that the `controller` of the\n * proof's verification method matches the identifier used for the `issuer` or `holder`, and that\n * the verification method is expressed under a verification relationship acceptable for the\n * proof's purpose. The latter is enforced by dereferencing the key with `purpose`.\n *\n * Verifying the proof only establishes that *someone* signed; without this comparison a document\n * could name one party and be signed by an unrelated one.\n *\n * @param expectedSigner the `issuer` or `holder`. `Holder` is optional in\n * VCDM 2.0 so when undefined there is no claim to contradict, so the validation passes.\n */\n private async verifySignerIsExpectedParty(\n agentContext: AgentContext,\n securedDocument: { proof: unknown },\n purpose: 'assertionMethod' | 'authentication',\n expectedSigner: string | undefined,\n describeMismatch: (verificationMethodId: string, expectedSigner: string) => string\n ): Promise<SingleValidationResult> {\n if (!expectedSigner) {\n return { isValid: true }\n }\n\n try {\n const verificationMethod = await getVerificationMethodForDataIntegrityProof(\n agentContext,\n securedDocument,\n purpose,\n expectedSigner\n )\n\n // NOTE: as in the JWT service's holder check, this compares verificationMethod.controller\n // rather than verificationMethod.id, since issuer and holder identify an entity rather than\n // a specific key.\n if (verificationMethod.controller !== expectedSigner) {\n return {\n isValid: false,\n error: new CredoError(describeMismatch(verificationMethod.id, expectedSigner)),\n }\n }\n\n return { isValid: true }\n } catch (error) {\n return { isValid: false, error }\n }\n }\n\n private invalidResult(errors: DataIntegrityIssueList, target: 'credential'): W3cV2VerifyCredentialResult\n private invalidResult(errors: DataIntegrityIssueList, target: 'presentation'): W3cV2VerifyPresentationResult\n private invalidResult(\n errors: DataIntegrityIssueList,\n target: 'credential' | 'presentation'\n ): W3cV2VerifyCredentialResult | W3cV2VerifyPresentationResult {\n const invalidValidation = this.invalidValidation(errors)\n\n if (target === 'credential') {\n return {\n isValid: false,\n validations: {\n signature: invalidValidation,\n },\n }\n }\n\n return this.invalidPresentationResult('presentationSignature', invalidValidation.error)\n }\n\n private invalidValidation(errors: DataIntegrityIssueList) {\n return {\n isValid: false,\n error: createDataIntegrityCredoError(errors),\n } as const\n }\n\n private invalidPresentationResult(\n field: 'dataModel' | 'presentationSignature',\n error: Error\n ): W3cV2VerifyPresentationResult {\n return {\n isValid: false,\n presentation: {\n isValid: false,\n validations: {\n [field]: {\n isValid: false,\n error,\n },\n },\n },\n credentialEntries: [],\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"W3cV2DataIntegrityCredentialService.mjs","names":["createDataIntegrityCredoError"],"sources":["../../../../src/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.ts"],"sourcesContent":["import type { AgentContext } from '../../../agent/context'\nimport { TrustedIssuerContext } from '../../../agent/TrustedIssuerContext'\nimport { CredoError } from '../../../error'\nimport { injectable } from '../../../plugins'\nimport { JsonTransformer, MessageValidator } from '../../../utils'\nimport {\n createW3cDataIntegrityCredoError as createDataIntegrityCredoError,\n type W3cDataIntegrityIssueList as DataIntegrityIssueList,\n W3cDataIntegrityProofService as DataIntegrityProofService,\n} from '../../w3c-di/internal'\nimport { CREDENTIALS_CONTEXT_V2_URL } from '../constants'\nimport { ClaimFormat } from '../models/ClaimFormat'\nimport { W3cV2Credential } from '../models/credential/W3cV2Credential'\nimport type { W3cV2VerifiableCredential } from '../models/credential/W3cV2VerifiableCredential'\nimport { W3cV2Presentation } from '../models/presentation/W3cV2Presentation'\nimport type { W3cV2VerifiablePresentation } from '../models/presentation/W3cV2VerifiablePresentation'\nimport type { W3cV2VerifyCredentialResult, W3cV2VerifyPresentationResult } from '../models/W3cV2VerifyResult'\nimport type { SingleValidationResult } from '../models/W3cVerifyResult'\nimport { type ResolvedSigner, validateSignerIsExpectedParty } from '../resolveSigner'\nimport { validateVc2ContextBaseline, validateVc2CredentialStatus } from '../validators'\nimport type {\n W3cV2DiSignCredentialOptions,\n W3cV2DiSignPresentationOptions,\n W3cV2DiVerifyCredentialOptions,\n W3cV2DiVerifyPresentationOptions,\n} from '../W3cV2CredentialServiceOptions'\nimport { resolveDataIntegritySigner } from './v2-di-utils'\nimport { W3cV2DataIntegrityContextValidator } from './W3cV2DataIntegrityContextValidator'\nimport { W3cV2DataIntegrityVerifiableCredential } from './W3cV2DataIntegrityVerifiableCredential'\nimport { W3cV2DataIntegrityVerifiablePresentation } from './W3cV2DataIntegrityVerifiablePresentation'\n\n@injectable()\nexport class W3cV2DataIntegrityCredentialService {\n private dataIntegrityProofService: DataIntegrityProofService\n private contextValidator: W3cV2DataIntegrityContextValidator\n\n public constructor(\n dataIntegrityProofService: DataIntegrityProofService,\n contextValidator: W3cV2DataIntegrityContextValidator\n ) {\n this.dataIntegrityProofService = dataIntegrityProofService\n this.contextValidator = contextValidator\n }\n\n public async signCredential(\n agentContext: AgentContext,\n options: W3cV2DiSignCredentialOptions\n ): Promise<W3cV2VerifiableCredential<ClaimFormat.DiVc>> {\n const unsecuredCredential = JsonTransformer.toJSON(options.credential)\n if (unsecuredCredential['@context'] === undefined || unsecuredCredential['@context'] === null) {\n unsecuredCredential['@context'] = [CREDENTIALS_CONTEXT_V2_URL]\n }\n\n MessageValidator.validateSync(JsonTransformer.fromJSON(unsecuredCredential, W3cV2Credential, { validate: false }))\n\n const contextValidation = validateVc2ContextBaseline(unsecuredCredential['@context'])\n if (!contextValidation.isValid) {\n throw contextValidation.error ?? new CredoError('VC2 credential @context validation failed')\n }\n\n const proofResult = await this.dataIntegrityProofService.createProof(agentContext, {\n unsecuredDocument: unsecuredCredential,\n verificationMethod: options.verificationMethod,\n proofPurpose: 'assertionMethod',\n cryptosuite: options.cryptosuite,\n })\n\n if (!proofResult.created) {\n throw createDataIntegrityCredoError(proofResult.errors)\n }\n\n return new W3cV2DataIntegrityVerifiableCredential({\n securedCredential: {\n ...unsecuredCredential,\n proof: proofResult.proof,\n },\n })\n }\n\n public async verifyCredential(\n agentContext: AgentContext,\n options: W3cV2DiVerifyCredentialOptions\n ): Promise<W3cV2VerifyCredentialResult> {\n const securedCredential = options.credential.securedCredential\n const verificationResult = Array.isArray(securedCredential.proof)\n ? await this.dataIntegrityProofService.verifyProofSetAndChain(agentContext, securedCredential as never, {\n expectedProofPurpose: 'assertionMethod',\n })\n : await this.dataIntegrityProofService.verifyProof(agentContext, securedCredential as never, {\n expectedProofPurpose: 'assertionMethod',\n })\n\n if (!verificationResult.verified) {\n return this.invalidResult(verificationResult.errors, 'credential')\n }\n\n const contextResult = await this.contextValidator.validate(agentContext, securedCredential)\n if (!contextResult.validated) {\n return this.invalidResult(contextResult.errors as DataIntegrityIssueList, 'credential')\n }\n\n const credentialStatus = validateVc2CredentialStatus({\n credentialStatus: securedCredential.credentialStatus,\n credentialFormat: 'DI',\n verifyCredentialStatus: options.verifyCredentialStatus,\n })\n\n const { validation: issuerIsSigner, signer: issuer } = await this.verifySignerIsExpectedParty(\n agentContext,\n securedCredential,\n 'assertionMethod',\n options.credential.resolvedCredential.issuerId,\n 'issuer'\n )\n\n const validations = {\n dataModel: { isValid: true },\n signature: { isValid: true },\n credentialStatus,\n issuerIsSigner,\n }\n\n if (issuer && issuerIsSigner.isValid) {\n try {\n await TrustedIssuerContext.ensureTrustedCredentialSigner(\n agentContext,\n {\n signer: { method: 'did', didUrl: issuer.verificationMethod.id },\n verification: { type: 'credential', credential: options.credential },\n },\n options.trustedIssuers\n )\n } catch (error) {\n return { isValid: false, validations, error }\n }\n }\n\n return {\n isValid: credentialStatus.isValid && issuerIsSigner.isValid,\n validations,\n }\n }\n\n public async signPresentation(\n agentContext: AgentContext,\n options: W3cV2DiSignPresentationOptions\n ): Promise<W3cV2VerifiablePresentation<ClaimFormat.DiVp>> {\n const unsecuredPresentation = JsonTransformer.toJSON(options.presentation)\n if (unsecuredPresentation['@context'] === undefined || unsecuredPresentation['@context'] === null) {\n unsecuredPresentation['@context'] = [CREDENTIALS_CONTEXT_V2_URL]\n }\n\n MessageValidator.validateSync(\n JsonTransformer.fromJSON(unsecuredPresentation, W3cV2Presentation, { validate: false })\n )\n\n const contextValidation = validateVc2ContextBaseline(unsecuredPresentation['@context'])\n if (!contextValidation.isValid) {\n throw contextValidation.error ?? new CredoError('VC2 presentation @context validation failed')\n }\n\n const proofResult = await this.dataIntegrityProofService.createProof(agentContext, {\n unsecuredDocument: unsecuredPresentation,\n verificationMethod: options.verificationMethod,\n proofPurpose: 'authentication',\n cryptosuite: options.cryptosuite,\n challenge: options.challenge,\n domain: options.domain,\n })\n\n if (!proofResult.created) {\n throw createDataIntegrityCredoError(proofResult.errors)\n }\n\n const securedPresentation = {\n ...unsecuredPresentation,\n proof: proofResult.proof,\n }\n\n return new W3cV2DataIntegrityVerifiablePresentation({\n securedPresentation,\n resolvedPresentation: JsonTransformer.fromJSON(securedPresentation, W3cV2Presentation, { validate: false }),\n })\n }\n\n public async verifyPresentation(\n agentContext: AgentContext,\n options: W3cV2DiVerifyPresentationOptions\n ): Promise<W3cV2VerifyPresentationResult> {\n const securedPresentation = options.presentation.securedPresentation\n\n const verificationResult = Array.isArray(securedPresentation.proof)\n ? await this.dataIntegrityProofService.verifyProofSetAndChain(agentContext, securedPresentation as never, {\n expectedProofPurpose: 'authentication',\n challenge: options.challenge,\n domain: options.domain,\n })\n : await this.dataIntegrityProofService.verifyProof(agentContext, securedPresentation as never, {\n expectedProofPurpose: 'authentication',\n challenge: options.challenge,\n domain: options.domain,\n })\n\n if (!verificationResult.verified) {\n return this.invalidResult(verificationResult.errors, 'presentation')\n }\n\n const presentationContextResult = await this.contextValidator.validate(agentContext, securedPresentation)\n if (!presentationContextResult.validated) {\n return this.invalidResult(presentationContextResult.errors as DataIntegrityIssueList, 'presentation')\n }\n\n const { validation: holderIsSigner } = await this.verifySignerIsExpectedParty(\n agentContext,\n options.presentation.securedPresentation,\n 'authentication',\n options.presentation.resolvedPresentation.holderId,\n 'holder'\n )\n\n return {\n isValid: holderIsSigner.isValid,\n presentation: {\n isValid: holderIsSigner.isValid,\n validations: {\n dataModel: { isValid: true },\n holderIsSigner,\n presentationSignature: { isValid: true },\n },\n },\n credentialEntries: [],\n }\n }\n\n private async verifySignerIsExpectedParty(\n agentContext: AgentContext,\n securedDocument: { proof: unknown },\n purpose: 'assertionMethod' | 'authentication',\n expectedSigner: string | undefined,\n role: 'issuer' | 'holder'\n ): Promise<{ validation: SingleValidationResult; signer?: ResolvedSigner }> {\n if (!expectedSigner) {\n return { validation: { isValid: true } }\n }\n\n try {\n const signer = await resolveDataIntegritySigner(agentContext, securedDocument, purpose, expectedSigner)\n return { validation: validateSignerIsExpectedParty(signer, expectedSigner, role), signer }\n } catch (error) {\n return { validation: { isValid: false, error } }\n }\n }\n\n private invalidResult(errors: DataIntegrityIssueList, target: 'credential'): W3cV2VerifyCredentialResult\n private invalidResult(errors: DataIntegrityIssueList, target: 'presentation'): W3cV2VerifyPresentationResult\n private invalidResult(\n errors: DataIntegrityIssueList,\n target: 'credential' | 'presentation'\n ): W3cV2VerifyCredentialResult | W3cV2VerifyPresentationResult {\n const invalidValidation = this.invalidValidation(errors)\n\n if (target === 'credential') {\n return {\n isValid: false,\n validations: {\n signature: invalidValidation,\n },\n }\n }\n\n return this.invalidPresentationResult('presentationSignature', invalidValidation.error)\n }\n\n private invalidValidation(errors: DataIntegrityIssueList) {\n return {\n isValid: false,\n error: createDataIntegrityCredoError(errors),\n } as const\n }\n\n private invalidPresentationResult(\n field: 'dataModel' | 'presentationSignature',\n error: Error\n ): W3cV2VerifyPresentationResult {\n return {\n isValid: false,\n presentation: {\n isValid: false,\n validations: {\n [field]: {\n isValid: false,\n error,\n },\n },\n },\n credentialEntries: [],\n }\n }\n}\n"],"mappings":"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"}
@@ -2,8 +2,8 @@ import { CredoError } from "../../../error/CredoError.mjs";
2
2
  import "../../../error/index.mjs";
3
3
  import { asArray } from "../../../utils/array.mjs";
4
4
  import "../../../utils/index.mjs";
5
- import { DidsApi } from "../../dids/DidsApi.mjs";
6
- import "../../dids/index.mjs";
5
+ import { tryParseDid } from "../../dids/domain/parse.mjs";
6
+ import { resolveSigner } from "../resolveSigner.mjs";
7
7
  //#region src/modules/vc/data-integrity/v2-di-utils.ts
8
8
  function isDataIntegrityProof(proof) {
9
9
  if (typeof proof !== "object" || proof === null) return false;
@@ -14,52 +14,34 @@ function getProofs(securedDocument) {
14
14
  return asArray(securedDocument.proof).filter(isDataIntegrityProof);
15
15
  }
16
16
  /**
17
- * Resolves the verification method that secured a Data Integrity credential or presentation for
18
- * an already verified proof or proof set.
19
- *
20
- * Mirrors `getVerificationMethodForJwt` for the Data Integrity securing mechanism, so that all
21
- * three securing mechanisms derive a signer the same way at the call site.
17
+ * Resolves the signer of a Data Integrity credential or presentation for an already verified proof
18
+ * or proof set.
22
19
  *
23
20
  * A `proof` value may be a proof set, which per VC-DATA-INTEGRITY has no order. Its proof purposes
24
21
  * have already been validated by w3c-di before this helper is called. Where several proofs name
25
- * different verification methods, position therefore carries no meaning. `expectedController` is
26
- * used to disambiguate: the proof whose verification method is controlled by that identity is
27
- * selected. This is the co-signature case — several parties sign, and only the one identified as
28
- * the issuer or holder is relevant here.
22
+ * different verification methods, position therefore carries no meaning. `expectedSigner` is
23
+ * used to disambiguate: the proof signed by that identity is selected. This is the co-signature
24
+ * case — several parties sign, and only the one identified as the issuer or holder is relevant here.
29
25
  *
30
- * @param expectedController the identity the signer is expected to be, where known — the
26
+ * @param expectedSigner the identity the signer is expected to be, where known — the
31
27
  * credential's `issuer` or the presentation's `holder`. Omit when unknown, in which case an
32
28
  * ambiguous proof set is rejected rather than resolved arbitrarily.
33
29
  *
34
30
  * @throws {CredoError} if there is no proof with a verification method, if several verification
35
- * methods cannot be disambiguated, or if a verification method cannot be resolved.
31
+ * methods cannot be disambiguated, or if a verification method cannot be resolved or is controlled
32
+ * by another DID.
36
33
  */
37
- async function getVerificationMethodForDataIntegrityProof(agentContext, securedDocument, purpose, expectedController) {
34
+ async function resolveDataIntegritySigner(agentContext, securedDocument, purpose, expectedSigner) {
38
35
  const proofs = getProofs(securedDocument);
39
36
  if (proofs.length === 0) throw new CredoError("Data Integrity secured document does not contain a proof with a verification method");
40
- const didsApi = agentContext.dependencyManager.resolve(DidsApi);
41
- const resolveVerificationMethod = async (verificationMethodId) => {
42
- return (await didsApi.resolveDidDocument(verificationMethodId)).dereferenceKey(verificationMethodId, [purpose]);
43
- };
44
37
  const verificationMethodIds = new Set(proofs.map((proof) => proof.verificationMethod));
45
- if (verificationMethodIds.size === 1) return resolveVerificationMethod(proofs[0].verificationMethod);
46
- if (!expectedController) throw new CredoError(`Data Integrity secured document contains multiple proofs with different verification methods (${[...verificationMethodIds].join(", ")}). Unable to determine the signer.`);
47
- const matching = (await Promise.all([...verificationMethodIds].map(resolveVerificationMethod))).filter((verificationMethod) => verificationMethod.controller === expectedController);
48
- if (matching.length === 0) throw new CredoError(`Data Integrity secured document contains multiple proofs, none of which is controlled by '${expectedController}'`);
49
- return matching[0];
50
- }
51
- /**
52
- * Resolves the identity that secured a Data Integrity credential or presentation for the given
53
- * proof purpose.
54
- *
55
- * @param expectedController see `getVerificationMethodForDataIntegrityProof`.
56
- */
57
- async function getSignerForDataIntegrityProof(agentContext, securedDocument, purpose, expectedController) {
58
- const verificationMethod = await getVerificationMethodForDataIntegrityProof(agentContext, securedDocument, purpose, expectedController);
59
- if (!verificationMethod.controller) throw new CredoError(`Verification method '${verificationMethod.id}' does not have a controller to use as the signer`);
60
- return verificationMethod.controller;
38
+ if (verificationMethodIds.size === 1) return resolveSigner(agentContext, proofs[0].verificationMethod, [purpose]);
39
+ if (!expectedSigner) throw new CredoError(`Data Integrity secured document contains multiple proofs with different verification methods (${[...verificationMethodIds].join(", ")}). Unable to determine the signer.`);
40
+ const expectedSignerVerificationMethodId = [...verificationMethodIds].find((verificationMethodId) => tryParseDid(verificationMethodId)?.did === expectedSigner);
41
+ if (!expectedSignerVerificationMethodId) throw new CredoError(`Data Integrity secured document contains multiple proofs, none of which is signed by '${expectedSigner}'`);
42
+ return resolveSigner(agentContext, expectedSignerVerificationMethodId, [purpose]);
61
43
  }
62
44
  //#endregion
63
- export { getSignerForDataIntegrityProof, getVerificationMethodForDataIntegrityProof };
45
+ export { resolveDataIntegritySigner };
64
46
 
65
47
  //# sourceMappingURL=v2-di-utils.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"v2-di-utils.mjs","names":[],"sources":["../../../../src/modules/vc/data-integrity/v2-di-utils.ts"],"sourcesContent":["import type { AgentContext } from '../../../agent'\nimport { CredoError } from '../../../error'\nimport { asArray } from '../../../utils'\nimport { type DidPurpose, DidsApi, type VerificationMethod } from '../../dids'\n\n/**\n * A Data Integrity proof, narrowed to the properties needed to identify the signer.\n */\ntype DataIntegrityProof = {\n verificationMethod: string\n}\n\nfunction isDataIntegrityProof(proof: unknown): proof is DataIntegrityProof {\n if (typeof proof !== 'object' || proof === null) return false\n\n const { verificationMethod } = proof as Record<string, unknown>\n return typeof verificationMethod === 'string'\n}\n\n/**\n * The part of a Data Integrity secured document this module needs: the embedded proof or proof\n * set. Both secured credentials and secured presentations satisfy this.\n */\ntype DataIntegritySecuredDocument = { proof: unknown }\n\nfunction getProofs(securedDocument: DataIntegritySecuredDocument): DataIntegrityProof[] {\n return asArray(securedDocument.proof).filter(isDataIntegrityProof)\n}\n\n/**\n * Resolves the verification method that secured a Data Integrity credential or presentation for\n * an already verified proof or proof set.\n *\n * Mirrors `getVerificationMethodForJwt` for the Data Integrity securing mechanism, so that all\n * three securing mechanisms derive a signer the same way at the call site.\n *\n * A `proof` value may be a proof set, which per VC-DATA-INTEGRITY has no order. Its proof purposes\n * have already been validated by w3c-di before this helper is called. Where several proofs name\n * different verification methods, position therefore carries no meaning. `expectedController` is\n * used to disambiguate: the proof whose verification method is controlled by that identity is\n * selected. This is the co-signature case — several parties sign, and only the one identified as\n * the issuer or holder is relevant here.\n *\n * @param expectedController the identity the signer is expected to be, where known — the\n * credential's `issuer` or the presentation's `holder`. Omit when unknown, in which case an\n * ambiguous proof set is rejected rather than resolved arbitrarily.\n *\n * @throws {CredoError} if there is no proof with a verification method, if several verification\n * methods cannot be disambiguated, or if a verification method cannot be resolved.\n */\nexport async function getVerificationMethodForDataIntegrityProof(\n agentContext: AgentContext,\n securedDocument: DataIntegritySecuredDocument,\n purpose: DidPurpose,\n expectedController?: string\n): Promise<VerificationMethod> {\n const proofs = getProofs(securedDocument)\n\n if (proofs.length === 0) {\n throw new CredoError('Data Integrity secured document does not contain a proof with a verification method')\n }\n\n const didsApi = agentContext.dependencyManager.resolve(DidsApi)\n\n const resolveVerificationMethod = async (verificationMethodId: string) => {\n const didDocument = await didsApi.resolveDidDocument(verificationMethodId)\n return didDocument.dereferenceKey(verificationMethodId, [purpose])\n }\n\n const verificationMethodIds = new Set(proofs.map((proof) => proof.verificationMethod))\n\n if (verificationMethodIds.size === 1) {\n return resolveVerificationMethod(proofs[0].verificationMethod)\n }\n\n if (!expectedController) {\n throw new CredoError(\n `Data Integrity secured document contains multiple proofs with different verification methods (${[...verificationMethodIds].join(', ')}). Unable to determine the signer.`\n )\n }\n\n const resolved = await Promise.all([...verificationMethodIds].map(resolveVerificationMethod))\n const matching = resolved.filter((verificationMethod) => verificationMethod.controller === expectedController)\n\n if (matching.length === 0) {\n throw new CredoError(\n `Data Integrity secured document contains multiple proofs, none of which is controlled by '${expectedController}'`\n )\n }\n\n return matching[0]\n}\n\n/**\n * Resolves the identity that secured a Data Integrity credential or presentation for the given\n * proof purpose.\n *\n * @param expectedController see `getVerificationMethodForDataIntegrityProof`.\n */\nexport async function getSignerForDataIntegrityProof(\n agentContext: AgentContext,\n securedDocument: DataIntegritySecuredDocument,\n purpose: DidPurpose,\n expectedController?: string\n): Promise<string> {\n const verificationMethod = await getVerificationMethodForDataIntegrityProof(\n agentContext,\n securedDocument,\n purpose,\n expectedController\n )\n\n if (!verificationMethod.controller) {\n throw new CredoError(\n `Verification method '${verificationMethod.id}' does not have a controller to use as the signer`\n )\n }\n\n return verificationMethod.controller\n}\n"],"mappings":";;;;;;;AAYA,SAAS,qBAAqB,OAA6C;CACzE,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO;CAExD,MAAM,EAAE,uBAAuB;CAC/B,OAAO,OAAO,uBAAuB;AACvC;AAQA,SAAS,UAAU,iBAAqE;CACtF,OAAO,QAAQ,gBAAgB,KAAK,CAAC,CAAC,OAAO,oBAAoB;AACnE;;;;;;;;;;;;;;;;;;;;;;AAuBA,eAAsB,2CACpB,cACA,iBACA,SACA,oBAC6B;CAC7B,MAAM,SAAS,UAAU,eAAe;CAExC,IAAI,OAAO,WAAW,GACpB,MAAM,IAAI,WAAW,qFAAqF;CAG5G,MAAM,UAAU,aAAa,kBAAkB,QAAQ,OAAO;CAE9D,MAAM,4BAA4B,OAAO,yBAAiC;EAExE,QAAO,MADmB,QAAQ,mBAAmB,oBAAoB,EAAA,CACtD,eAAe,sBAAsB,CAAC,OAAO,CAAC;CACnE;CAEA,MAAM,wBAAwB,IAAI,IAAI,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;CAErF,IAAI,sBAAsB,SAAS,GACjC,OAAO,0BAA0B,OAAO,EAAE,CAAC,kBAAkB;CAG/D,IAAI,CAAC,oBACH,MAAM,IAAI,WACR,iGAAiG,CAAC,GAAG,qBAAqB,CAAC,CAAC,KAAK,IAAI,EAAE,mCACzI;CAIF,MAAM,YAAW,MADM,QAAQ,IAAI,CAAC,GAAG,qBAAqB,CAAC,CAAC,IAAI,yBAAyB,CAAC,EAAA,CAClE,QAAQ,uBAAuB,mBAAmB,eAAe,kBAAkB;CAE7G,IAAI,SAAS,WAAW,GACtB,MAAM,IAAI,WACR,6FAA6F,mBAAmB,EAClH;CAGF,OAAO,SAAS;AAClB;;;;;;;AAQA,eAAsB,+BACpB,cACA,iBACA,SACA,oBACiB;CACjB,MAAM,qBAAqB,MAAM,2CAC/B,cACA,iBACA,SACA,kBACF;CAEA,IAAI,CAAC,mBAAmB,YACtB,MAAM,IAAI,WACR,wBAAwB,mBAAmB,GAAG,kDAChD;CAGF,OAAO,mBAAmB;AAC5B"}
1
+ {"version":3,"file":"v2-di-utils.mjs","names":[],"sources":["../../../../src/modules/vc/data-integrity/v2-di-utils.ts"],"sourcesContent":["import type { AgentContext } from '../../../agent'\nimport { CredoError } from '../../../error'\nimport { asArray } from '../../../utils'\nimport type { DidPurpose } from '../../dids'\nimport { tryParseDid } from '../../dids/domain/parse'\nimport { type ResolvedSigner, resolveSigner } from '../resolveSigner'\n\n/**\n * A Data Integrity proof, narrowed to the properties needed to identify the signer.\n */\ntype DataIntegrityProof = {\n verificationMethod: string\n}\n\nfunction isDataIntegrityProof(proof: unknown): proof is DataIntegrityProof {\n if (typeof proof !== 'object' || proof === null) return false\n\n const { verificationMethod } = proof as Record<string, unknown>\n return typeof verificationMethod === 'string'\n}\n\n/**\n * The part of a Data Integrity secured document this module needs: the embedded proof or proof\n * set. Both secured credentials and secured presentations satisfy this.\n */\ntype DataIntegritySecuredDocument = { proof: unknown }\n\nfunction getProofs(securedDocument: DataIntegritySecuredDocument): DataIntegrityProof[] {\n return asArray(securedDocument.proof).filter(isDataIntegrityProof)\n}\n\n/**\n * Resolves the signer of a Data Integrity credential or presentation for an already verified proof\n * or proof set.\n *\n * A `proof` value may be a proof set, which per VC-DATA-INTEGRITY has no order. Its proof purposes\n * have already been validated by w3c-di before this helper is called. Where several proofs name\n * different verification methods, position therefore carries no meaning. `expectedSigner` is\n * used to disambiguate: the proof signed by that identity is selected. This is the co-signature\n * case — several parties sign, and only the one identified as the issuer or holder is relevant here.\n *\n * @param expectedSigner the identity the signer is expected to be, where known — the\n * credential's `issuer` or the presentation's `holder`. Omit when unknown, in which case an\n * ambiguous proof set is rejected rather than resolved arbitrarily.\n *\n * @throws {CredoError} if there is no proof with a verification method, if several verification\n * methods cannot be disambiguated, or if a verification method cannot be resolved or is controlled\n * by another DID.\n */\nexport async function resolveDataIntegritySigner(\n agentContext: AgentContext,\n securedDocument: DataIntegritySecuredDocument,\n purpose: DidPurpose,\n expectedSigner?: string\n): Promise<ResolvedSigner> {\n const proofs = getProofs(securedDocument)\n\n if (proofs.length === 0) {\n throw new CredoError('Data Integrity secured document does not contain a proof with a verification method')\n }\n\n const verificationMethodIds = new Set(proofs.map((proof) => proof.verificationMethod))\n\n if (verificationMethodIds.size === 1) {\n return resolveSigner(agentContext, proofs[0].verificationMethod, [purpose])\n }\n\n if (!expectedSigner) {\n throw new CredoError(\n `Data Integrity secured document contains multiple proofs with different verification methods (${[...verificationMethodIds].join(', ')}). Unable to determine the signer.`\n )\n }\n\n // The signer is the DID of the verification method, so the other proofs don't need to be resolved\n const expectedSignerVerificationMethodId = [...verificationMethodIds].find(\n (verificationMethodId) => tryParseDid(verificationMethodId)?.did === expectedSigner\n )\n\n if (!expectedSignerVerificationMethodId) {\n throw new CredoError(\n `Data Integrity secured document contains multiple proofs, none of which is signed by '${expectedSigner}'`\n )\n }\n\n return resolveSigner(agentContext, expectedSignerVerificationMethodId, [purpose])\n}\n"],"mappings":";;;;;;;AAcA,SAAS,qBAAqB,OAA6C;CACzE,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO;CAExD,MAAM,EAAE,uBAAuB;CAC/B,OAAO,OAAO,uBAAuB;AACvC;AAQA,SAAS,UAAU,iBAAqE;CACtF,OAAO,QAAQ,gBAAgB,KAAK,CAAC,CAAC,OAAO,oBAAoB;AACnE;;;;;;;;;;;;;;;;;;;AAoBA,eAAsB,2BACpB,cACA,iBACA,SACA,gBACyB;CACzB,MAAM,SAAS,UAAU,eAAe;CAExC,IAAI,OAAO,WAAW,GACpB,MAAM,IAAI,WAAW,qFAAqF;CAG5G,MAAM,wBAAwB,IAAI,IAAI,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;CAErF,IAAI,sBAAsB,SAAS,GACjC,OAAO,cAAc,cAAc,OAAO,EAAE,CAAC,oBAAoB,CAAC,OAAO,CAAC;CAG5E,IAAI,CAAC,gBACH,MAAM,IAAI,WACR,iGAAiG,CAAC,GAAG,qBAAqB,CAAC,CAAC,KAAK,IAAI,EAAE,mCACzI;CAIF,MAAM,qCAAqC,CAAC,GAAG,qBAAqB,CAAC,CAAC,MACnE,yBAAyB,YAAY,oBAAoB,CAAC,EAAE,QAAQ,cACvE;CAEA,IAAI,CAAC,oCACH,MAAM,IAAI,WACR,yFAAyF,eAAe,EAC1G;CAGF,OAAO,cAAc,cAAc,oCAAoC,CAAC,OAAO,CAAC;AAClF"}
@@ -40,29 +40,6 @@ export declare class W3cJwtCredentialService {
40
40
  */
41
41
  verifyPresentation(agentContext: AgentContext, options: W3cJwtVerifyPresentationOptions): Promise<W3cVerifyPresentationResult>;
42
42
  private resolveVerificationMethod;
43
- /**
44
- * This method tries to find the verification method associated with the JWT credential or presentation.
45
- * This verification method can then be used to verify the credential or presentation signature.
46
- *
47
- * The following methods are used to extract the verification method:
48
- * - verification method is resolved based on the `kid` in the protected header
49
- * - either as absolute reference (e.g. `did:example:123#key-1`)
50
- * - or as relative reference to the `iss` of the JWT (e.g. `iss` is `did:example:123` and `kid` is `#key-1`)
51
- * - the did document is resolved based on the `iss` field, after which the verification method is extracted based on the `alg`
52
- * used to sign the JWT and the specified `purpose`. Only a single verification method may be present, and in all other cases,
53
- * an error is thrown.
54
- *
55
- * The signer (`iss`) of the JWT is verified against the `controller` of the verificationMethod resolved in the did
56
- * document. This means if the `iss` of a credential is `did:example:123` and the controller of the verificationMethod
57
- * is `did:example:456`, an error is thrown to prevent the JWT from successfully being verified.
58
- *
59
- * In addition the JWT must conform to one of the following rules:
60
- * - MUST be a credential and have an `iss` field and MAY have an absolute or relative `kid`
61
- * - MUST not be a credential AND ONE of the following:
62
- * - have an `iss` field and MAY have an absolute or relative `kid`
63
- * - does not have an `iss` field and MUST have an absolute `kid`
64
- */
65
- private getVerificationMethodForJwtCredential;
66
43
  }
67
44
  //#endregion
68
45
  //# sourceMappingURL=W3cJwtCredentialService.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"W3cJwtCredentialService.d.mts","names":[],"sources":["../../../../src/modules/vc/jwt-vc/W3cJwtCredentialService.ts"],"mappings":";;;;;;;;;;;;;qBAiCa;UACH;EAEW,YAAA,YAAY;;;;EAOlB,eACX,cAAc,cACd,SAAS,8BACR,QAAQ;;;;;;;EAuCE,iBACX,cAAc,cACd,SAAS,gCACR,QAAQ;;;;;;;EAkJE,iBACX,cAAc,cACd,SAAS,gCACR,QAAQ;;;;;;;EAqCE,mBACX,cAAc,cACd,SAAS,kCACR,QAAQ;UAsJG;;;;;;;;;;;;;;;;;;;;;;;UAyCA"}
1
+ {"version":3,"file":"W3cJwtCredentialService.d.mts","names":[],"sources":["../../../../src/modules/vc/jwt-vc/W3cJwtCredentialService.ts"],"mappings":";;;;;;;;;;;;;qBA+Ba;UACH;EAEW,YAAA,YAAY;;;;EAOlB,eACX,cAAc,cACd,SAAS,8BACR,QAAQ;;;;;;;EAuCE,iBACX,cAAc,cACd,SAAS,gCACR,QAAQ;;;;;;;EA8HE,iBACX,cAAc,cACd,SAAS,gCACR,QAAQ;;;;;;;EAqCE,mBACX,cAAc,cACd,SAAS,kCACR,QAAQ;UA8IG"}