@credo-ts/core 0.7.3 → 0.7.4-alpha-20261028231852

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 (80) 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/crypto/webcrypto/CredoWalletWebCrypto.d.mts +1 -1
  8. package/build/index.d.mts +3 -3
  9. package/build/index.mjs +2 -2
  10. package/build/modules/dcql/DcqlService.d.mts.map +1 -1
  11. package/build/modules/dcql/DcqlService.mjs +24 -12
  12. package/build/modules/dcql/DcqlService.mjs.map +1 -1
  13. package/build/modules/dids/services/DidResolverService.d.mts +4 -0
  14. package/build/modules/dids/services/DidResolverService.d.mts.map +1 -1
  15. package/build/modules/dids/services/DidResolverService.mjs +21 -5
  16. package/build/modules/dids/services/DidResolverService.mjs.map +1 -1
  17. package/build/modules/sd-jwt-vc/utils.mjs +4 -4
  18. package/build/modules/sd-jwt-vc/utils.mjs.map +1 -1
  19. package/build/modules/vc/W3cCredentialServiceOptions.d.mts +5 -5
  20. package/build/modules/vc/W3cCredentialServiceOptions.d.mts.map +1 -1
  21. package/build/modules/vc/W3cV2CredentialService.d.mts +5 -1
  22. package/build/modules/vc/W3cV2CredentialService.d.mts.map +1 -1
  23. package/build/modules/vc/W3cV2CredentialService.mjs +72 -26
  24. package/build/modules/vc/W3cV2CredentialService.mjs.map +1 -1
  25. package/build/modules/vc/W3cV2CredentialServiceOptions.d.mts +14 -6
  26. package/build/modules/vc/W3cV2CredentialServiceOptions.d.mts.map +1 -1
  27. package/build/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.d.mts +0 -18
  28. package/build/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.d.mts.map +1 -1
  29. package/build/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.mjs +38 -36
  30. package/build/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.mjs.map +1 -1
  31. package/build/modules/vc/data-integrity/v2-di-utils.mjs +17 -35
  32. package/build/modules/vc/data-integrity/v2-di-utils.mjs.map +1 -1
  33. package/build/modules/vc/jwt-vc/W3cJwtCredentialService.d.mts +0 -23
  34. package/build/modules/vc/jwt-vc/W3cJwtCredentialService.d.mts.map +1 -1
  35. package/build/modules/vc/jwt-vc/W3cJwtCredentialService.mjs +17 -68
  36. package/build/modules/vc/jwt-vc/W3cJwtCredentialService.mjs.map +1 -1
  37. package/build/modules/vc/jwt-vc/W3cV2JwtCredentialService.d.mts.map +1 -1
  38. package/build/modules/vc/jwt-vc/W3cV2JwtCredentialService.mjs +11 -17
  39. package/build/modules/vc/jwt-vc/W3cV2JwtCredentialService.mjs.map +1 -1
  40. package/build/modules/vc/linked-data-proofs/W3cJsonLdCredentialService.d.mts +5 -0
  41. package/build/modules/vc/linked-data-proofs/W3cJsonLdCredentialService.d.mts.map +1 -1
  42. package/build/modules/vc/linked-data-proofs/W3cJsonLdCredentialService.mjs +18 -4
  43. package/build/modules/vc/linked-data-proofs/W3cJsonLdCredentialService.mjs.map +1 -1
  44. package/build/modules/vc/models/W3cV2VerifyResult.d.mts +6 -0
  45. package/build/modules/vc/models/W3cV2VerifyResult.d.mts.map +1 -1
  46. package/build/modules/vc/models/credential/W3cV2EnvelopedVerifiableCredential.d.mts +1 -1
  47. package/build/modules/vc/models/credential/W3cV2EnvelopedVerifiableCredential.d.mts.map +1 -1
  48. package/build/modules/vc/models/credential/W3cV2VerifiableCredential.d.mts +1 -1
  49. package/build/modules/vc/models/credential/W3cV2VerifiableCredential.d.mts.map +1 -1
  50. package/build/modules/vc/resolveSigner.mjs +74 -0
  51. package/build/modules/vc/resolveSigner.mjs.map +1 -0
  52. package/build/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.d.mts.map +1 -1
  53. package/build/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.mjs +16 -18
  54. package/build/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.mjs.map +1 -1
  55. package/build/modules/vc/sd-jwt-vc/disclosureFrame.d.mts +1 -1
  56. package/build/modules/vc/sd-jwt-vc/disclosureFrame.d.mts.map +1 -1
  57. package/build/modules/vc/sd-jwt-vc/disclosureFrame.mjs +2 -1
  58. package/build/modules/vc/sd-jwt-vc/disclosureFrame.mjs.map +1 -1
  59. package/build/modules/vc/v2-jwt-utils.mjs +54 -55
  60. package/build/modules/vc/v2-jwt-utils.mjs.map +1 -1
  61. package/build/modules/x509/X509ModuleConfig.d.mts +5 -13
  62. package/build/modules/x509/X509ModuleConfig.d.mts.map +1 -1
  63. package/build/modules/x509/X509ModuleConfig.mjs +2 -1
  64. package/build/modules/x509/X509ModuleConfig.mjs.map +1 -1
  65. package/build/modules/x509/X509RevocationService.d.mts.map +1 -1
  66. package/build/modules/x509/X509RevocationService.mjs +17 -20
  67. package/build/modules/x509/X509RevocationService.mjs.map +1 -1
  68. package/build/modules/x509/X509Service.mjs +1 -1
  69. package/build/modules/x509/X509Service.mjs.map +1 -1
  70. package/build/modules/x509/X509ServiceOptions.d.mts +4 -6
  71. package/build/modules/x509/X509ServiceOptions.d.mts.map +1 -1
  72. package/build/modules/x509/X509ValidationOptions.d.mts +19 -2
  73. package/build/modules/x509/X509ValidationOptions.d.mts.map +1 -1
  74. package/build/modules/x509/X509ValidationOptions.mjs +21 -1
  75. package/build/modules/x509/X509ValidationOptions.mjs.map +1 -1
  76. package/build/modules/x509/index.d.mts +2 -2
  77. package/build/modules/x509/index.mjs +2 -2
  78. package/build/modules/x509/utils/crlFetcher.mjs +1 -11
  79. package/build/modules/x509/utils/crlFetcher.mjs.map +1 -1
  80. package/package.json +1 -1
@@ -4,7 +4,11 @@ import { asArray } from "../../utils/array.mjs";
4
4
  import { injectable } from "../../plugins/index.mjs";
5
5
  import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.mjs";
6
6
  import __decorate from "../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.mjs";
7
+ import { getPublicJwkFromVerificationMethod } from "../dids/domain/key-type/keyDidMapping.mjs";
8
+ import "../dids/index.mjs";
7
9
  import "./models/ClaimFormat.mjs";
10
+ import "./resolveSigner.mjs";
11
+ import { extractKeyFromHolderBinding, parseHolderBindingFromCredential } from "../sd-jwt-vc/utils.mjs";
8
12
  import { W3cV2JwtVerifiableCredential } from "./jwt-vc/W3cV2JwtVerifiableCredential.mjs";
9
13
  import { W3cV2DataIntegrityVerifiableCredential } from "./data-integrity/W3cV2DataIntegrityVerifiableCredential.mjs";
10
14
  import { W3cV2DataIntegrityVerifiablePresentation } from "./data-integrity/W3cV2DataIntegrityVerifiablePresentation.mjs";
@@ -13,10 +17,10 @@ import { W3cV2EnvelopedVerifiableCredential } from "./models/credential/W3cV2Env
13
17
  import { W3cV2EnvelopedVerifiablePresentation } from "./models/presentation/W3cV2EnvelopedVerifiablePresentation.mjs";
14
18
  import { W3cV2JwtVerifiablePresentation } from "./jwt-vc/W3cV2JwtVerifiablePresentation.mjs";
15
19
  import { W3cV2SdJwtVerifiablePresentation } from "./sd-jwt-vc/W3cV2SdJwtVerifiablePresentation.mjs";
16
- import { getVerificationMethodForJwt } from "./v2-jwt-utils.mjs";
20
+ import { getSignerForJwt } from "./v2-jwt-utils.mjs";
17
21
  import { W3cV2JwtCredentialService } from "./jwt-vc/W3cV2JwtCredentialService.mjs";
18
22
  import "./jwt-vc/index.mjs";
19
- import { getSignerForDataIntegrityProof } from "./data-integrity/v2-di-utils.mjs";
23
+ import { resolveDataIntegritySigner } from "./data-integrity/v2-di-utils.mjs";
20
24
  import { W3cV2DataIntegrityCredentialService } from "./data-integrity/W3cV2DataIntegrityCredentialService.mjs";
21
25
  import "./data-integrity/index.mjs";
22
26
  import { W3cV2SdJwtCredentialService } from "./sd-jwt-vc/W3cV2SdJwtCredentialService.mjs";
@@ -117,7 +121,7 @@ let W3cV2CredentialService = class W3cV2CredentialService {
117
121
  credentialEntries: []
118
122
  };
119
123
  let entries = [];
120
- let signerId;
124
+ let signer;
121
125
  if (presentation instanceof W3cV2JwtVerifiablePresentation) {
122
126
  const presentationResult = await this.w3cV2JwtCredentialService.verifyPresentation(agentContext, {
123
127
  ...options,
@@ -126,12 +130,11 @@ let W3cV2CredentialService = class W3cV2CredentialService {
126
130
  validationResults.presentation = presentationResult.presentation;
127
131
  if (!presentationResult.presentation.isValid) {
128
132
  validationResults.isValid = false;
133
+ validationResults.error = presentationResult.error;
129
134
  return validationResults;
130
135
  }
131
- const holderId = presentation.resolvedPresentation.holderId;
132
- if (holderId) signerId = holderId;
133
- else try {
134
- signerId = (await getVerificationMethodForJwt(agentContext, presentation, ["authentication"])).controller;
136
+ try {
137
+ signer = await getSignerForJwt(agentContext, presentation, ["authentication"]);
135
138
  } catch (error) {
136
139
  validationResults.isValid = false;
137
140
  validationResults.error = error;
@@ -146,12 +149,11 @@ let W3cV2CredentialService = class W3cV2CredentialService {
146
149
  validationResults.presentation = presentationResult.presentation;
147
150
  if (!presentationResult.presentation.isValid) {
148
151
  validationResults.isValid = false;
152
+ validationResults.error = presentationResult.error;
149
153
  return validationResults;
150
154
  }
151
- const holderId = presentation.resolvedPresentation.holderId;
152
- if (holderId) signerId = holderId;
153
- else try {
154
- signerId = (await getVerificationMethodForJwt(agentContext, presentation, ["authentication"])).controller;
155
+ try {
156
+ signer = await getSignerForJwt(agentContext, presentation, ["authentication"]);
155
157
  } catch (error) {
156
158
  validationResults.isValid = false;
157
159
  validationResults.error = error;
@@ -166,11 +168,11 @@ let W3cV2CredentialService = class W3cV2CredentialService {
166
168
  validationResults.presentation = presentationResult.presentation;
167
169
  if (!presentationResult.presentation.isValid) {
168
170
  validationResults.isValid = false;
171
+ validationResults.error = presentationResult.error;
169
172
  return validationResults;
170
173
  }
171
- signerId = presentation.resolvedPresentation.holderId;
172
- if (!signerId) try {
173
- signerId = await getSignerForDataIntegrityProof(agentContext, presentation.securedPresentation, "authentication");
174
+ try {
175
+ signer = await resolveDataIntegritySigner(agentContext, presentation.securedPresentation, "authentication", presentation.resolvedPresentation.holderId);
174
176
  } catch (error) {
175
177
  validationResults.isValid = false;
176
178
  validationResults.error = error;
@@ -178,24 +180,67 @@ let W3cV2CredentialService = class W3cV2CredentialService {
178
180
  }
179
181
  entries = this.extractCredentialEntriesFromPresentation(presentation);
180
182
  } else throw new CredoError("Unsupported credential type in options. Presentation must be either a W3cV2JwtVerifiablePresentation, a W3cV2SdJwtVerifiablePresentation, or a W3cV2DataIntegrityVerifiablePresentation");
181
- validationResults.credentialEntries = (await Promise.all(entries.map((entry) => this.verifyPresentationEntry(agentContext, entry, signerId)))).flat();
183
+ validationResults.credentialEntries = (await Promise.all(entries.map((entry) => this.verifyPresentationEntry(agentContext, entry, signer, options.trustedIssuers, {
184
+ nonce: options.challenge,
185
+ audience: options.domain
186
+ })))).flat();
182
187
  validationResults.isValid = validationResults.presentation.isValid && validationResults.credentialEntries.every((entry) => entry.isValid);
183
188
  return validationResults;
184
189
  }
185
- async verifyPresentationEntry(agentContext, entry, signerId) {
190
+ async verifyPresentationEntry(agentContext, entry, signer, trustedIssuers, presentationBinding) {
186
191
  if (entry instanceof W3cV2DataIntegrityVerifiablePresentation) return [this.createInvalidCredentialEntryResult(new CredoError("Nested verifiable presentation entries are not supported in VC 2.0 presentations."))];
187
192
  if (entry instanceof W3cV2DataIntegrityVerifiableCredential) {
188
- const credentialResult = await this.w3cV2DataIntegrityCredentialService.verifyCredential(agentContext, { credential: entry });
189
- return [this.mergeCredentialSubjectAuthenticationValidation(credentialResult, signerId, entry.resolvedCredential?.credentialSubjectIds ?? [])];
193
+ const credentialResult = await this.w3cV2DataIntegrityCredentialService.verifyCredential(agentContext, {
194
+ credential: entry,
195
+ trustedIssuers
196
+ });
197
+ return [this.mergeHolderValidations(credentialResult, signer, entry.resolvedCredential?.credentialSubjectIds ?? [], { isValid: true })];
190
198
  }
191
199
  if (entry instanceof W3cV2EnvelopedVerifiablePresentation) return [this.createInvalidCredentialEntryResult(new CredoError("Nested verifiable presentation entries are not supported in VC 2.0 presentations."))];
192
200
  if (!(entry instanceof W3cV2EnvelopedVerifiableCredential)) return [this.createInvalidCredentialEntryResult(new CredoError("Unsupported credential entry type in presentation."))];
193
201
  const enclosed = entry.envelopedCredential;
194
202
  let credentialResult;
195
- if (enclosed instanceof W3cV2JwtVerifiableCredential) credentialResult = await this.w3cV2JwtCredentialService.verifyCredential(agentContext, { credential: enclosed });
196
- else if (enclosed instanceof W3cV2SdJwtVerifiableCredential) credentialResult = await this.w3cV2SdJwtCredentialService.verifyCredential(agentContext, { credential: enclosed });
197
- else return [this.createInvalidCredentialEntryResult(new CredoError(`Credential entry uses '${this.getClaimFormat(enclosed) ?? "an unsupported enclosed credential format"}'.`))];
198
- return [this.mergeCredentialSubjectAuthenticationValidation(credentialResult, signerId, entry.resolvedCredential.credentialSubjectIds)];
203
+ let claims;
204
+ if (enclosed instanceof W3cV2JwtVerifiableCredential) {
205
+ credentialResult = await this.w3cV2JwtCredentialService.verifyCredential(agentContext, {
206
+ credential: enclosed,
207
+ trustedIssuers
208
+ });
209
+ claims = enclosed.jwt.payload.toJson();
210
+ } else if (enclosed instanceof W3cV2SdJwtVerifiableCredential) {
211
+ const { nonce, audience } = presentationBinding;
212
+ if (enclosed.sdJwt.kbJwt && !audience) return [this.createInvalidCredentialEntryResult(new CredoError("Credential has a KB-JWT, but no domain is provided to verify its audience"))];
213
+ credentialResult = await this.w3cV2SdJwtCredentialService.verifyCredential(agentContext, {
214
+ credential: enclosed,
215
+ trustedIssuers,
216
+ keyBinding: enclosed.sdJwt.kbJwt && audience ? {
217
+ nonce,
218
+ audience
219
+ } : void 0
220
+ });
221
+ claims = enclosed.sdJwt.prettyClaims;
222
+ } else return [this.createInvalidCredentialEntryResult(new CredoError(`Credential entry uses '${this.getClaimFormat(enclosed) ?? "an unsupported enclosed credential format"}'.`))];
223
+ return [this.mergeHolderValidations(credentialResult, signer, entry.resolvedCredential.credentialSubjectIds, await this.verifyHolderBinding(agentContext, claims, signer))];
224
+ }
225
+ /**
226
+ * A credential bound to a key with `cnf` must be presented with that key.
227
+ */
228
+ async verifyHolderBinding(agentContext, claims, signer) {
229
+ try {
230
+ const holderBinding = parseHolderBindingFromCredential(claims);
231
+ if (!holderBinding) return { isValid: true };
232
+ const { publicJwk } = await extractKeyFromHolderBinding(agentContext, holderBinding, { didPurposes: ["authentication"] });
233
+ if (publicJwk.equals(getPublicJwkFromVerificationMethod(signer.verificationMethod))) return { isValid: true };
234
+ return {
235
+ isValid: false,
236
+ error: new CredoError(`Credential is bound to a different key than verification method ${signer.verificationMethod.id} that signed the presentation`)
237
+ };
238
+ } catch (error) {
239
+ return {
240
+ isValid: false,
241
+ error
242
+ };
243
+ }
199
244
  }
200
245
  extractCredentialEntriesFromPresentation(presentation) {
201
246
  return this.extractCredentialEntriesFromResolvedPresentation(presentation.resolvedPresentation);
@@ -215,18 +260,19 @@ let W3cV2CredentialService = class W3cV2CredentialService {
215
260
  const candidate = value;
216
261
  return typeof candidate.claimFormat === "string" ? candidate.claimFormat : void 0;
217
262
  }
218
- mergeCredentialSubjectAuthenticationValidation(credentialResult, signerId, credentialSubjectIds) {
219
- const presentationAuthenticatesCredentialSubject = credentialSubjectIds.some((subjectId) => signerId === subjectId);
263
+ mergeHolderValidations(credentialResult, signer, credentialSubjectIds, holderBinding) {
264
+ const presentationAuthenticatesCredentialSubject = credentialSubjectIds.some((subjectId) => signer.signer === subjectId);
220
265
  const credentialSubjectAuthentication = credentialSubjectIds.length > 0 && !presentationAuthenticatesCredentialSubject ? {
221
266
  isValid: false,
222
267
  error: new CredoError("Credential has one or more credentialSubject ids, but presentation does not authenticate credential subject")
223
268
  } : { isValid: true };
224
269
  return {
225
270
  ...credentialResult,
226
- isValid: credentialResult.isValid && credentialSubjectAuthentication.isValid,
271
+ isValid: credentialResult.isValid && credentialSubjectAuthentication.isValid && holderBinding.isValid,
227
272
  validations: {
228
273
  ...credentialResult.validations,
229
- credentialSubjectAuthentication
274
+ credentialSubjectAuthentication,
275
+ holderBinding
230
276
  }
231
277
  };
232
278
  }
@@ -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":";;;;;;;;;;;;;;;;;;;;AA8BO,IAAM,sCAAN,MAAM,oCAAoC;CAI/C,YACE,2BACA,kBACA;EACA,KAAK,4BAA4B;EACjC,KAAK,mBAAmB;CAC1B;CAEA,MAAa,eACX,cACA,SACsD;EACtD,MAAM,sBAAsB,gBAAgB,OAAO,QAAQ,UAAU;EACrE,IAAI,oBAAoB,gBAAgB,KAAA,KAAa,oBAAoB,gBAAgB,MACvF,oBAAoB,cAAc,CAAC,0BAA0B;EAG/D,iBAAiB,aAAa,gBAAgB,SAAS,qBAAqB,iBAAiB,EAAE,UAAU,MAAM,CAAC,CAAC;EAEjH,MAAM,oBAAoB,2BAA2B,oBAAoB,WAAW;EACpF,IAAI,CAAC,kBAAkB,SACrB,MAAM,kBAAkB,SAAS,IAAI,WAAW,2CAA2C;EAG7F,MAAM,cAAc,MAAM,KAAK,0BAA0B,YAAY,cAAc;GACjF,mBAAmB;GACnB,oBAAoB,QAAQ;GAC5B,cAAc;GACd,aAAa,QAAQ;EACvB,CAAC;EAED,IAAI,CAAC,YAAY,SACf,MAAMA,iCAA8B,YAAY,MAAM;EAGxD,OAAO,IAAI,uCAAuC,EAChD,mBAAmB;GACjB,GAAG;GACH,OAAO,YAAY;EACrB,EACF,CAAC;CACH;CAEA,MAAa,iBACX,cACA,SACsC;EACtC,MAAM,oBAAoB,QAAQ,WAAW;EAC7C,MAAM,qBAAqB,MAAM,QAAQ,kBAAkB,KAAK,IAC5D,MAAM,KAAK,0BAA0B,uBAAuB,cAAc,mBAA4B,EACpG,sBAAsB,kBACxB,CAAC,IACD,MAAM,KAAK,0BAA0B,YAAY,cAAc,mBAA4B,EACzF,sBAAsB,kBACxB,CAAC;EAEL,IAAI,CAAC,mBAAmB,UACtB,OAAO,KAAK,cAAc,mBAAmB,QAAQ,YAAY;EAGnE,MAAM,gBAAgB,MAAM,KAAK,iBAAiB,SAAS,cAAc,iBAAiB;EAC1F,IAAI,CAAC,cAAc,WACjB,OAAO,KAAK,cAAc,cAAc,QAAkC,YAAY;EAGxF,MAAM,mBAAmB,4BAA4B;GACnD,kBAAkB,kBAAkB;GACpC,kBAAkB;GAClB,wBAAwB,QAAQ;EAClC,CAAC;EAED,MAAM,iBAAiB,MAAM,KAAK,4BAChC,cACA,mBACA,mBACA,QAAQ,WAAW,mBAAmB,WACrC,sBAAsB,aACrB,kDAAkD,qBAAqB,2CAA2C,SAAS,EAC/H;EAIA,OAAO;GACL,SAHc,iBAAiB,WAAW,eAAe;GAIzD,aAAa;IACX,WAAW,EAAE,SAAS,KAAK;IAC3B,WAAW,EAAE,SAAS,KAAK;IAC3B;IACA;GACF;EACF;CACF;CAEA,MAAa,iBACX,cACA,SACwD;EACxD,MAAM,wBAAwB,gBAAgB,OAAO,QAAQ,YAAY;EACzE,IAAI,sBAAsB,gBAAgB,KAAA,KAAa,sBAAsB,gBAAgB,MAC3F,sBAAsB,cAAc,CAAC,0BAA0B;EAGjE,iBAAiB,aACf,gBAAgB,SAAS,uBAAuB,mBAAmB,EAAE,UAAU,MAAM,CAAC,CACxF;EAEA,MAAM,oBAAoB,2BAA2B,sBAAsB,WAAW;EACtF,IAAI,CAAC,kBAAkB,SACrB,MAAM,kBAAkB,SAAS,IAAI,WAAW,6CAA6C;EAG/F,MAAM,cAAc,MAAM,KAAK,0BAA0B,YAAY,cAAc;GACjF,mBAAmB;GACnB,oBAAoB,QAAQ;GAC5B,cAAc;GACd,aAAa,QAAQ;GACrB,WAAW,QAAQ;GACnB,QAAQ,QAAQ;EAClB,CAAC;EAED,IAAI,CAAC,YAAY,SACf,MAAMA,iCAA8B,YAAY,MAAM;EAGxD,MAAM,sBAAsB;GAC1B,GAAG;GACH,OAAO,YAAY;EACrB;EAEA,OAAO,IAAI,yCAAyC;GAClD;GACA,sBAAsB,gBAAgB,SAAS,qBAAqB,mBAAmB,EAAE,UAAU,MAAM,CAAC;EAC5G,CAAC;CACH;CAEA,MAAa,mBACX,cACA,SACwC;EACxC,MAAM,sBAAsB,QAAQ,aAAa;EAEjD,MAAM,qBAAqB,MAAM,QAAQ,oBAAoB,KAAK,IAC9D,MAAM,KAAK,0BAA0B,uBAAuB,cAAc,qBAA8B;GACtG,sBAAsB;GACtB,WAAW,QAAQ;GACnB,QAAQ,QAAQ;EAClB,CAAC,IACD,MAAM,KAAK,0BAA0B,YAAY,cAAc,qBAA8B;GAC3F,sBAAsB;GACtB,WAAW,QAAQ;GACnB,QAAQ,QAAQ;EAClB,CAAC;EAEL,IAAI,CAAC,mBAAmB,UACtB,OAAO,KAAK,cAAc,mBAAmB,QAAQ,cAAc;EAGrE,MAAM,4BAA4B,MAAM,KAAK,iBAAiB,SAAS,cAAc,mBAAmB;EACxG,IAAI,CAAC,0BAA0B,WAC7B,OAAO,KAAK,cAAc,0BAA0B,QAAkC,cAAc;EAGtG,MAAM,iBAAiB,MAAM,KAAK,4BAChC,cACA,QAAQ,aAAa,qBACrB,kBACA,QAAQ,aAAa,qBAAqB,WACzC,sBAAsB,aACrB,oDAAoD,qBAAqB,6CAA6C,SAAS,EACnI;EAEA,OAAO;GACL,SAAS,eAAe;GACxB,cAAc;IACZ,SAAS,eAAe;IACxB,aAAa;KACX,WAAW,EAAE,SAAS,KAAK;KAC3B;KACA,uBAAuB,EAAE,SAAS,KAAK;IACzC;GACF;GACA,mBAAmB,CAAC;EACtB;CACF;;;;;;;;;;;;;;;;;;;CAoBA,MAAc,4BACZ,cACA,iBACA,SACA,gBACA,kBACiC;EACjC,IAAI,CAAC,gBACH,OAAO,EAAE,SAAS,KAAK;EAGzB,IAAI;GACF,MAAM,qBAAqB,MAAM,2CAC/B,cACA,iBACA,SACA,cACF;GAKA,IAAI,mBAAmB,eAAe,gBACpC,OAAO;IACL,SAAS;IACT,OAAO,IAAI,WAAW,iBAAiB,mBAAmB,IAAI,cAAc,CAAC;GAC/E;GAGF,OAAO,EAAE,SAAS,KAAK;EACzB,SAAS,OAAO;GACd,OAAO;IAAE,SAAS;IAAO;GAAM;EACjC;CACF;CAIA,cACE,QACA,QAC6D;EAC7D,MAAM,oBAAoB,KAAK,kBAAkB,MAAM;EAEvD,IAAI,WAAW,cACb,OAAO;GACL,SAAS;GACT,aAAa,EACX,WAAW,kBACb;EACF;EAGF,OAAO,KAAK,0BAA0B,yBAAyB,kBAAkB,KAAK;CACxF;CAEA,kBAA0B,QAAgC;EACxD,OAAO;GACL,SAAS;GACT,OAAOA,iCAA8B,MAAM;EAC7C;CACF;CAEA,0BACE,OACA,OAC+B;EAC/B,OAAO;GACL,SAAS;GACT,cAAc;IACZ,SAAS;IACT,aAAa,GACV,QAAQ;KACP,SAAS;KACT;IACF,EACF;GACF;GACA,mBAAmB,CAAC;EACtB;CACF;AACF;AAhSC,sCAAA,WAAA,CAAA,WAAW,GAAA,mBAAA,qBAAA,CAAA,OAAA,iCAAA,cAAA,SAAA,8BAAA,OAAA,uCAAA,cAAA,SAAA,kCAAA,CAAA,CAAA,GAAA,mCAAA"}
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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"}