@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.
- package/build/agent/TrustedIssuerContext.d.mts +11 -1
- package/build/agent/TrustedIssuerContext.d.mts.map +1 -1
- package/build/agent/TrustedIssuerContext.mjs +7 -0
- package/build/agent/TrustedIssuerContext.mjs.map +1 -1
- package/build/agent/TrustedIssuersForVerification.d.mts +11 -1
- package/build/agent/TrustedIssuersForVerification.d.mts.map +1 -1
- package/build/crypto/webcrypto/CredoWalletWebCrypto.d.mts +1 -1
- package/build/index.d.mts +3 -3
- package/build/index.mjs +2 -2
- package/build/modules/dcql/DcqlService.d.mts.map +1 -1
- package/build/modules/dcql/DcqlService.mjs +24 -12
- package/build/modules/dcql/DcqlService.mjs.map +1 -1
- package/build/modules/dids/services/DidResolverService.d.mts +4 -0
- package/build/modules/dids/services/DidResolverService.d.mts.map +1 -1
- package/build/modules/dids/services/DidResolverService.mjs +21 -5
- package/build/modules/dids/services/DidResolverService.mjs.map +1 -1
- package/build/modules/sd-jwt-vc/utils.mjs +4 -4
- package/build/modules/sd-jwt-vc/utils.mjs.map +1 -1
- package/build/modules/vc/W3cCredentialServiceOptions.d.mts +5 -5
- package/build/modules/vc/W3cCredentialServiceOptions.d.mts.map +1 -1
- package/build/modules/vc/W3cV2CredentialService.d.mts +5 -1
- package/build/modules/vc/W3cV2CredentialService.d.mts.map +1 -1
- package/build/modules/vc/W3cV2CredentialService.mjs +72 -26
- package/build/modules/vc/W3cV2CredentialService.mjs.map +1 -1
- package/build/modules/vc/W3cV2CredentialServiceOptions.d.mts +14 -6
- package/build/modules/vc/W3cV2CredentialServiceOptions.d.mts.map +1 -1
- package/build/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.d.mts +0 -18
- package/build/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.d.mts.map +1 -1
- package/build/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.mjs +38 -36
- package/build/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.mjs.map +1 -1
- package/build/modules/vc/data-integrity/v2-di-utils.mjs +17 -35
- package/build/modules/vc/data-integrity/v2-di-utils.mjs.map +1 -1
- package/build/modules/vc/jwt-vc/W3cJwtCredentialService.d.mts +0 -23
- package/build/modules/vc/jwt-vc/W3cJwtCredentialService.d.mts.map +1 -1
- package/build/modules/vc/jwt-vc/W3cJwtCredentialService.mjs +17 -68
- package/build/modules/vc/jwt-vc/W3cJwtCredentialService.mjs.map +1 -1
- package/build/modules/vc/jwt-vc/W3cV2JwtCredentialService.d.mts.map +1 -1
- package/build/modules/vc/jwt-vc/W3cV2JwtCredentialService.mjs +11 -17
- package/build/modules/vc/jwt-vc/W3cV2JwtCredentialService.mjs.map +1 -1
- package/build/modules/vc/linked-data-proofs/W3cJsonLdCredentialService.d.mts +5 -0
- package/build/modules/vc/linked-data-proofs/W3cJsonLdCredentialService.d.mts.map +1 -1
- package/build/modules/vc/linked-data-proofs/W3cJsonLdCredentialService.mjs +18 -4
- package/build/modules/vc/linked-data-proofs/W3cJsonLdCredentialService.mjs.map +1 -1
- package/build/modules/vc/models/W3cV2VerifyResult.d.mts +6 -0
- package/build/modules/vc/models/W3cV2VerifyResult.d.mts.map +1 -1
- package/build/modules/vc/models/credential/W3cV2EnvelopedVerifiableCredential.d.mts +1 -1
- package/build/modules/vc/models/credential/W3cV2EnvelopedVerifiableCredential.d.mts.map +1 -1
- package/build/modules/vc/models/credential/W3cV2VerifiableCredential.d.mts +1 -1
- package/build/modules/vc/models/credential/W3cV2VerifiableCredential.d.mts.map +1 -1
- package/build/modules/vc/resolveSigner.mjs +74 -0
- package/build/modules/vc/resolveSigner.mjs.map +1 -0
- package/build/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.d.mts.map +1 -1
- package/build/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.mjs +16 -18
- package/build/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.mjs.map +1 -1
- package/build/modules/vc/sd-jwt-vc/disclosureFrame.d.mts +1 -1
- package/build/modules/vc/sd-jwt-vc/disclosureFrame.d.mts.map +1 -1
- package/build/modules/vc/sd-jwt-vc/disclosureFrame.mjs +2 -1
- package/build/modules/vc/sd-jwt-vc/disclosureFrame.mjs.map +1 -1
- package/build/modules/vc/v2-jwt-utils.mjs +54 -55
- package/build/modules/vc/v2-jwt-utils.mjs.map +1 -1
- package/build/modules/x509/X509ModuleConfig.d.mts +5 -13
- package/build/modules/x509/X509ModuleConfig.d.mts.map +1 -1
- package/build/modules/x509/X509ModuleConfig.mjs +2 -1
- package/build/modules/x509/X509ModuleConfig.mjs.map +1 -1
- package/build/modules/x509/X509RevocationService.d.mts.map +1 -1
- package/build/modules/x509/X509RevocationService.mjs +17 -20
- package/build/modules/x509/X509RevocationService.mjs.map +1 -1
- package/build/modules/x509/X509Service.mjs +1 -1
- package/build/modules/x509/X509Service.mjs.map +1 -1
- package/build/modules/x509/X509ServiceOptions.d.mts +4 -6
- package/build/modules/x509/X509ServiceOptions.d.mts.map +1 -1
- package/build/modules/x509/X509ValidationOptions.d.mts +19 -2
- package/build/modules/x509/X509ValidationOptions.d.mts.map +1 -1
- package/build/modules/x509/X509ValidationOptions.mjs +21 -1
- package/build/modules/x509/X509ValidationOptions.mjs.map +1 -1
- package/build/modules/x509/index.d.mts +2 -2
- package/build/modules/x509/index.mjs +2 -2
- package/build/modules/x509/utils/crlFetcher.mjs +1 -11
- package/build/modules/x509/utils/crlFetcher.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"W3cV2SdJwtCredentialService.mjs","names":[],"sources":["../../../../src/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.ts"],"sourcesContent":["import { type DisclosureFrame, type PresentationFrame, type SDJWTConfig, SDJwtInstance } from '@sd-jwt/core'\nimport type { AgentContext } from '../../../agent/context'\nimport { TrustedIssuerContext } from '../../../agent/TrustedIssuerContext'\nimport { JwtPayload } from '../../../crypto'\nimport { CredoError } from '../../../error'\nimport { injectable } from '../../../plugins'\nimport type { JsonObject } from '../../../types'\nimport { asArray, JsonTransformer, MessageValidator, nowInSeconds, TypedArrayEncoder } from '../../../utils'\nimport { getPublicJwkFromVerificationMethod } from '../../dids/domain/key-type/keyDidMapping'\nimport { KeyManagementApi } from '../../kms'\nimport type { IDisclosureFrame } from '../../sd-jwt-vc'\nimport { applyDisclosuresForPaths, applyDisclosuresForPayload, type ClaimPath } from '../../sd-jwt-vc/disclosureFrame'\nimport {\n extractKeyFromHolderBinding,\n getSdJwtHashingAlgorithm,\n getSdJwtSigner,\n getSdJwtVerifier,\n parseHolderBindingFromCredential,\n setJwkAlgFromJwtHeader,\n} from '../../sd-jwt-vc/utils'\nimport type {\n W3cV2JsonCredential,\n W3cV2JsonPresentation,\n W3cV2VerifyCredentialResult,\n W3cV2VerifyPresentationResult,\n} from '../models'\nimport {\n extractHolderFromPresentationCredentials,\n getVerificationMethodForJwt,\n validateAndResolveVerificationMethod,\n} from '../v2-jwt-utils'\nimport {\n validateVc2ContextBaseline,\n validateVc2CredentialStatus,\n validateVc2CredentialValidityPeriod,\n} from '../validators'\nimport type {\n W3cV2SdJwtSignCredentialOptions,\n W3cV2SdJwtSignPresentationOptions,\n W3cV2SdJwtVcPresentOptions,\n W3cV2SdJwtVerifyCredentialOptions,\n W3cV2SdJwtVerifyPresentationOptions,\n} from '../W3cV2CredentialServiceOptions'\nimport { validateW3cV2SdJwtDisclosureFrame } from './disclosureFrame'\nimport { sdJwtVcHasher } from './W3cV2SdJwt'\nimport { W3cV2SdJwtVerifiableCredential } from './W3cV2SdJwtVerifiableCredential'\nimport { W3cV2SdJwtVerifiablePresentation } from './W3cV2SdJwtVerifiablePresentation'\n\n/**\n * Supports signing and verifying W3C Verifiable Credentials and Presentations\n * secured with Selective Disclosure JSON Web Tokens (SD-JWT).\n *\n * @see https://www.w3.org/TR/vc-data-model/\n * @see https://www.w3.org/TR/vc-jose-cose/#with-sd-jwt\n */\n@injectable()\nexport class W3cV2SdJwtCredentialService {\n /**\n * Signs a credential\n */\n public async signCredential(\n agentContext: AgentContext,\n options: W3cV2SdJwtSignCredentialOptions\n ): Promise<W3cV2SdJwtVerifiableCredential> {\n // Validate the instance\n MessageValidator.validateSync(options.credential)\n\n // The JWT payload is simply the credential\n const payload = JsonTransformer.toJSON(options.credential) as W3cV2JsonCredential\n\n // Add iat and cnf to the payload\n payload.iat = nowInSeconds()\n payload.cnf = options.holder ? (await extractKeyFromHolderBinding(agentContext, options.holder)).cnf : undefined\n\n // Validate and resolve the verification method\n const publicJwk = await validateAndResolveVerificationMethod(agentContext, options.verificationMethod, [\n 'assertionMethod',\n ])\n\n // Validate the disclosure frame\n const disclosureFrame = options.disclosureFrame as DisclosureFrame<W3cV2JsonCredential> | undefined\n this.validateDisclosureFrame(disclosureFrame)\n\n publicJwk.alg = options.alg\n\n const sdJwt = new SDJwtInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n signer: getSdJwtSigner(agentContext, publicJwk),\n hashAlg: getSdJwtHashingAlgorithm(options.hashingAlgorithm),\n signAlg: options.alg,\n })\n\n // Sign SD-JWT\n const compact = await sdJwt.issue<W3cV2JsonCredential>(payload, disclosureFrame, {\n header: {\n typ: 'vc+sd-jwt',\n alg: options.alg,\n kid: options.verificationMethod,\n },\n })\n\n return W3cV2SdJwtVerifiableCredential.fromCompact(compact)\n }\n\n /**\n * Verifies the signature(s) of a credential\n *\n * @param credential the credential to be verified\n * @returns the verification result\n */\n public async verifyCredential(\n agentContext: AgentContext,\n options: W3cV2SdJwtVerifyCredentialOptions\n ): Promise<W3cV2VerifyCredentialResult> {\n const validationResults: W3cV2VerifyCredentialResult = {\n isValid: false,\n validations: {},\n }\n\n const sdJwt = new SDJwtInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n })\n\n try {\n let credential: W3cV2SdJwtVerifiableCredential\n try {\n // If instance is provided as input, we want to validate the credential\n // Otherwise, it is done by fromCompact below\n if (options.credential instanceof W3cV2SdJwtVerifiableCredential) {\n options.credential.validate()\n }\n\n credential =\n options.credential instanceof W3cV2SdJwtVerifiableCredential\n ? options.credential\n : W3cV2SdJwtVerifiableCredential.fromCompact(options.credential)\n\n // Validate JWT payload\n JwtPayload.fromJson(credential.sdJwt.payload).validate({\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n this.logCredentialShouldWarnings(agentContext, credential)\n\n validationResults.validations.dataModel = validateVc2ContextBaseline(credential.resolvedCredential.context)\n if (!validationResults.validations.dataModel.isValid) {\n return validationResults\n }\n\n validationResults.validations.dataModel = {\n isValid: true,\n }\n\n validationResults.validations.validityPeriod = validateVc2CredentialValidityPeriod({\n validFrom: credential.resolvedCredential.validFrom,\n validUntil: credential.resolvedCredential.validUntil,\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n validationResults.validations.credentialStatus = validateVc2CredentialStatus({\n credentialStatus: credential.resolvedCredential.credentialStatus,\n credentialFormat: 'SD-JWT',\n verifyCredentialStatus: options.verifyCredentialStatus,\n })\n } catch (error) {\n validationResults.validations.dataModel = {\n isValid: false,\n error,\n }\n\n return validationResults\n }\n\n const issuerVerificationMethod = await getVerificationMethodForJwt(agentContext, credential, ['assertionMethod'])\n const issuerPublicKey = getPublicJwkFromVerificationMethod(issuerVerificationMethod)\n\n // Ensure the issuer is trusted according to the (optional) `getTrustedIssuersForVerification`\n // callback. For did-based issuers this is a no-op when no trusted issuers are configured,\n // preserving the previous \"trust any valid signature\" behavior. Throws when the issuer is not trusted.\n await TrustedIssuerContext.ensureTrustedSigner(\n agentContext,\n {\n signer: { method: 'did', didUrl: issuerVerificationMethod.id },\n verification: { type: 'credential', credential },\n },\n options.trustedIssuers\n )\n\n const holderBinding = parseHolderBindingFromCredential(credential.sdJwt.prettyClaims)\n const holder = holderBinding ? await extractKeyFromHolderBinding(agentContext, holderBinding) : undefined\n\n setJwkAlgFromJwtHeader(issuerPublicKey, credential.sdJwt.header.alg)\n if (holder && credential.sdJwt.kbJwt) {\n setJwkAlgFromJwtHeader(holder.publicJwk, credential.sdJwt.kbJwt.header?.alg)\n }\n\n sdJwt.config({\n verifier: getSdJwtVerifier(agentContext, issuerPublicKey),\n kbVerifier: holder ? getSdJwtVerifier(agentContext, holder.publicJwk) : undefined,\n })\n\n try {\n await sdJwt.verify(credential.encoded, {\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n validationResults.validations.signature = {\n isValid: true,\n }\n } catch (error) {\n validationResults.validations.signature = {\n isValid: false,\n error,\n }\n }\n\n // Validate whether the credential is signed with the 'issuer' id\n // NOTE: this uses the verificationMethod.controller. We may want to use the verificationMethod.id?\n if (credential.resolvedCredential.issuerId !== issuerVerificationMethod.controller) {\n validationResults.validations.issuerIsSigner = {\n isValid: false,\n error: new CredoError(\n `Credential is signed using verification method ${issuerVerificationMethod.id}, while the issuer of the credential is '${credential.resolvedCredential.issuerId}'`\n ),\n }\n } else {\n validationResults.validations.issuerIsSigner = {\n isValid: true,\n }\n }\n\n validationResults.isValid = Object.values(validationResults.validations).every(\n (validation) => validation?.isValid === true\n )\n return validationResults\n } catch (error) {\n validationResults.error = error\n return validationResults\n }\n }\n\n /**\n * Signs a presentation including the credentials it includes\n *\n * @param presentation the presentation to be signed\n * @returns the signed presentation\n */\n public async signPresentation(\n agentContext: AgentContext,\n options: W3cV2SdJwtSignPresentationOptions\n ): Promise<W3cV2SdJwtVerifiablePresentation> {\n // Validate the instance\n MessageValidator.validateSync(options.presentation)\n\n // The JWT payload is simply the presentation\n const payload = JsonTransformer.toJSON(options.presentation) as W3cV2JsonPresentation\n\n // Add the nonce and aud to the payload\n payload.nonce = options.challenge\n payload.aud = options.domain\n\n const holder = await extractHolderFromPresentationCredentials(agentContext, options.presentation)\n\n holder.publicJwk.alg = holder.alg\n\n const sdJwt = new SDJwtInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n signer: getSdJwtSigner(agentContext, holder.publicJwk),\n hashAlg: getSdJwtHashingAlgorithm(options.hashingAlgorithm),\n signAlg: holder.alg,\n })\n\n // Validate the disclosure frame\n const disclosureFrame = options.disclosureFrame as DisclosureFrame<W3cV2JsonPresentation> | undefined\n this.validateDisclosureFrame(disclosureFrame)\n\n // Sign SD-JWT\n const compact = await sdJwt.issue<W3cV2JsonPresentation>(payload, disclosureFrame, {\n header: {\n typ: 'vp+sd-jwt',\n alg: holder.alg,\n kid: holder?.cnf?.kid,\n },\n })\n\n return W3cV2SdJwtVerifiablePresentation.fromCompact(compact)\n }\n\n /**\n * Verifies a presentation including the credentials it includes\n *\n * @param presentation the presentation to be verified\n * @returns the verification result\n */\n public async verifyPresentation(\n agentContext: AgentContext,\n options: W3cV2SdJwtVerifyPresentationOptions\n ): Promise<W3cV2VerifyPresentationResult> {\n const validationResults: W3cV2VerifyPresentationResult = {\n isValid: false,\n presentation: {\n isValid: false,\n validations: {},\n },\n credentialEntries: [],\n }\n\n const sdjwt = new SDJwtInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n })\n\n try {\n let presentation: W3cV2SdJwtVerifiablePresentation\n try {\n // If instance is provided as input, we want to validate the presentation\n if (options.presentation instanceof W3cV2SdJwtVerifiablePresentation) {\n options.presentation.validate()\n }\n\n presentation =\n options.presentation instanceof W3cV2SdJwtVerifiablePresentation\n ? options.presentation\n : W3cV2SdJwtVerifiablePresentation.fromCompact(options.presentation)\n\n // Validate JWT payload\n JwtPayload.fromJson(presentation.sdJwt.payload).validate({\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n this.logPresentationShouldWarnings(agentContext, presentation)\n\n // VC-JOSE-COSE: understood claims MUST be evaluated per verifier policy\n // https://www.w3.org/TR/vc-jose-cose/#validation-algorithm\n if (options.challenge !== presentation.sdJwt.prettyClaims.nonce) {\n throw new CredoError(`JWT payload 'nonce' does not match challenge '${options.challenge}'`)\n }\n\n const audArray = asArray(presentation.sdJwt.prettyClaims.aud)\n if (options.domain && !audArray.includes(options.domain)) {\n throw new CredoError(`JWT payload 'aud' does not include domain '${options.domain}'`)\n }\n\n const contextValidationResult = validateVc2ContextBaseline(presentation.resolvedPresentation.context)\n if (!contextValidationResult.isValid) {\n throw contextValidationResult.error\n }\n\n validationResults.presentation.validations.dataModel = {\n isValid: true,\n }\n } catch (error) {\n validationResults.presentation.validations.dataModel = {\n isValid: false,\n error,\n }\n\n return validationResults\n }\n\n const proverVerificationMethod = await getVerificationMethodForJwt(agentContext, presentation, ['authentication'])\n const proverPublicKey = getPublicJwkFromVerificationMethod(proverVerificationMethod)\n const holderBinding = parseHolderBindingFromCredential(presentation.sdJwt.prettyClaims)\n const holder = holderBinding ? await extractKeyFromHolderBinding(agentContext, holderBinding) : undefined\n\n setJwkAlgFromJwtHeader(proverPublicKey, presentation.sdJwt.header.alg)\n if (holder && presentation.sdJwt.kbJwt) {\n setJwkAlgFromJwtHeader(holder.publicJwk, presentation.sdJwt.kbJwt.header?.alg)\n }\n\n sdjwt.config({\n verifier: getSdJwtVerifier(agentContext, proverPublicKey),\n kbVerifier: holder ? getSdJwtVerifier(agentContext, holder.publicJwk) : undefined,\n })\n\n try {\n await sdjwt.verify(presentation.encoded, {\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n validationResults.presentation.validations.presentationSignature = {\n isValid: true,\n }\n } catch (error) {\n validationResults.presentation.validations.presentationSignature = {\n isValid: false,\n error,\n }\n }\n\n // Validate whether the presentation is signed with the 'holder' id\n // NOTE: this uses the verificationMethod.controller. We may want to use the verificationMethod.id?\n if (\n presentation.resolvedPresentation.holderId &&\n proverVerificationMethod.controller !== presentation.resolvedPresentation.holderId\n ) {\n validationResults.presentation.validations.holderIsSigner = {\n isValid: false,\n error: new CredoError(\n `Presentation is signed using verification method ${proverVerificationMethod.id}, while the holder of the presentation is '${presentation.resolvedPresentation.holderId}'`\n ),\n }\n } else {\n // If no holderId is present, this validation passes by default as there can't be\n // a mismatch between the 'holder' property and the signer of the presentation.\n validationResults.presentation.validations.holderIsSigner = {\n isValid: true,\n }\n }\n\n validationResults.presentation.isValid = Object.values(validationResults.presentation.validations).every(\n (validation) => validation.isValid\n )\n\n // Credential-entry dispatch is orchestrated by W3cV2CredentialService.\n // This service verifies VP container integrity only.\n validationResults.isValid = validationResults.presentation.isValid\n\n return validationResults\n } catch (error) {\n validationResults.error = error\n return validationResults\n }\n }\n\n public async present(\n agentContext: AgentContext,\n options: W3cV2SdJwtVcPresentOptions\n ): Promise<W3cV2SdJwtVerifiableCredential> {\n const originalCompact =\n options.credential instanceof W3cV2SdJwtVerifiableCredential ? options.credential.encoded : options.credential\n\n const presentationFrame = options.presentationFrame as PresentationFrame<W3cV2JsonCredential>\n\n const sdjwt = new SDJwtInstance(this.getBaseSdJwtConfig(agentContext))\n const disclosedCompact = await sdjwt.present(originalCompact, presentationFrame)\n\n return W3cV2SdJwtVerifiableCredential.fromCompact(disclosedCompact)\n }\n\n /**\n * @deprecated use `applyDisclosuresForPaths` instead\n */\n public applyDisclosuresForPayload(\n compactSdJwtVc: string,\n requestedPayload: JsonObject\n ): W3cV2SdJwtVerifiableCredential {\n const sdJwt = applyDisclosuresForPayload(compactSdJwtVc, requestedPayload)\n return W3cV2SdJwtVerifiableCredential.fromCompact(sdJwt)\n }\n\n public applyDisclosuresForPaths(compactSdJwtVc: string, disclosedPaths: ClaimPath[]): W3cV2SdJwtVerifiableCredential {\n const { compact } = applyDisclosuresForPaths(compactSdJwtVc, disclosedPaths)\n return W3cV2SdJwtVerifiableCredential.fromCompact(compact)\n }\n\n private validateDisclosureFrame(disclosureFrame?: DisclosureFrame<W3cV2JsonCredential | W3cV2JsonPresentation>) {\n validateW3cV2SdJwtDisclosureFrame(disclosureFrame as IDisclosureFrame | undefined)\n }\n\n private getBaseSdJwtConfig(agentContext: AgentContext): SDJWTConfig {\n const kms = agentContext.resolve(KeyManagementApi)\n\n return {\n hasher: sdJwtVcHasher,\n saltGenerator: (length) => TypedArrayEncoder.toBase64Url(kms.randomBytes({ length })).slice(0, length),\n }\n }\n\n private logCredentialShouldWarnings(agentContext: AgentContext, credential: W3cV2SdJwtVerifiableCredential) {\n const payload = credential.sdJwt.prettyClaims\n const headerIss = credential.sdJwt.header.iss\n\n if (typeof headerIss === 'string' && typeof payload.iss === 'string' && headerIss !== payload.iss) {\n agentContext.config.logger.warn('VC-JOSE-COSE SHOULD warning: JOSE header iss conflicts with payload iss', {\n format: 'vc+sd-jwt',\n headerIss,\n payloadIss: payload.iss,\n })\n }\n\n if (\n typeof payload.jti === 'string' &&\n credential.resolvedCredential.id &&\n credential.resolvedCredential.id !== payload.jti\n ) {\n agentContext.config.logger.warn('VC-JOSE-COSE SHOULD warning: jti claim conflicts with credential id', {\n format: 'vc+sd-jwt',\n jti: payload.jti,\n credentialId: credential.resolvedCredential.id,\n })\n }\n\n if (typeof payload.sub === 'string' && !credential.resolvedCredential.credentialSubjectIds.includes(payload.sub)) {\n agentContext.config.logger.warn(\n 'VC-JOSE-COSE SHOULD warning: sub claim does not match any credentialSubject.id',\n {\n format: 'vc+sd-jwt',\n sub: payload.sub,\n credentialSubjectIds: credential.resolvedCredential.credentialSubjectIds,\n }\n )\n }\n }\n\n private logPresentationShouldWarnings(agentContext: AgentContext, presentation: W3cV2SdJwtVerifiablePresentation) {\n const payload = presentation.sdJwt.prettyClaims\n const headerIss = presentation.sdJwt.header.iss\n\n if (typeof headerIss === 'string' && typeof payload.iss === 'string' && headerIss !== payload.iss) {\n agentContext.config.logger.warn('VC-JOSE-COSE SHOULD warning: JOSE header iss conflicts with payload iss', {\n format: 'vp+sd-jwt',\n headerIss,\n payloadIss: payload.iss,\n })\n }\n\n if (\n typeof payload.jti === 'string' &&\n presentation.resolvedPresentation.id &&\n presentation.resolvedPresentation.id !== payload.jti\n ) {\n agentContext.config.logger.warn('VC-JOSE-COSE SHOULD warning: jti claim conflicts with presentation id', {\n format: 'vp+sd-jwt',\n jti: payload.jti,\n presentationId: presentation.resolvedPresentation.id,\n })\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"W3cV2SdJwtCredentialService.mjs","names":[],"sources":["../../../../src/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.ts"],"sourcesContent":["import { type DisclosureFrame, type PresentationFrame, type SDJWTConfig, SDJwtInstance } from '@sd-jwt/core'\nimport type { AgentContext } from '../../../agent/context'\nimport { TrustedIssuerContext } from '../../../agent/TrustedIssuerContext'\nimport { JwtPayload } from '../../../crypto'\nimport { CredoError } from '../../../error'\nimport { injectable } from '../../../plugins'\nimport type { JsonObject } from '../../../types'\nimport { asArray, JsonTransformer, MessageValidator, nowInSeconds, TypedArrayEncoder } from '../../../utils'\nimport { getPublicJwkFromVerificationMethod } from '../../dids/domain/key-type/keyDidMapping'\nimport { KeyManagementApi } from '../../kms'\nimport type { IDisclosureFrame } from '../../sd-jwt-vc'\nimport { applyDisclosuresForPaths, applyDisclosuresForPayload, type ClaimPath } from '../../sd-jwt-vc/disclosureFrame'\nimport {\n extractKeyFromHolderBinding,\n getSdJwtHashingAlgorithm,\n getSdJwtSigner,\n getSdJwtVerifier,\n parseHolderBindingFromCredential,\n setJwkAlgFromJwtHeader,\n} from '../../sd-jwt-vc/utils'\nimport type {\n W3cV2JsonCredential,\n W3cV2JsonPresentation,\n W3cV2VerifyCredentialResult,\n W3cV2VerifyPresentationResult,\n} from '../models'\nimport { validateSignerIsExpectedParty } from '../resolveSigner'\nimport {\n extractHolderFromPresentationCredentials,\n getSignerForJwt,\n validateAndResolveVerificationMethod,\n} from '../v2-jwt-utils'\nimport {\n validateVc2ContextBaseline,\n validateVc2CredentialStatus,\n validateVc2CredentialValidityPeriod,\n} from '../validators'\nimport type {\n W3cV2SdJwtSignCredentialOptions,\n W3cV2SdJwtSignPresentationOptions,\n W3cV2SdJwtVcPresentOptions,\n W3cV2SdJwtVerifyCredentialOptions,\n W3cV2SdJwtVerifyPresentationOptions,\n} from '../W3cV2CredentialServiceOptions'\nimport { validateW3cV2SdJwtDisclosureFrame } from './disclosureFrame'\nimport { sdJwtVcHasher } from './W3cV2SdJwt'\nimport { W3cV2SdJwtVerifiableCredential } from './W3cV2SdJwtVerifiableCredential'\nimport { W3cV2SdJwtVerifiablePresentation } from './W3cV2SdJwtVerifiablePresentation'\n\n/**\n * Supports signing and verifying W3C Verifiable Credentials and Presentations\n * secured with Selective Disclosure JSON Web Tokens (SD-JWT).\n *\n * @see https://www.w3.org/TR/vc-data-model/\n * @see https://www.w3.org/TR/vc-jose-cose/#with-sd-jwt\n */\n@injectable()\nexport class W3cV2SdJwtCredentialService {\n /**\n * Signs a credential\n */\n public async signCredential(\n agentContext: AgentContext,\n options: W3cV2SdJwtSignCredentialOptions\n ): Promise<W3cV2SdJwtVerifiableCredential> {\n // Validate the instance\n MessageValidator.validateSync(options.credential)\n\n // The JWT payload is simply the credential\n const payload = JsonTransformer.toJSON(options.credential) as W3cV2JsonCredential\n\n // Add iat and cnf to the payload\n payload.iat = nowInSeconds()\n payload.cnf = options.holder\n ? (await extractKeyFromHolderBinding(agentContext, options.holder, { didPurposes: ['authentication'] })).cnf\n : undefined\n\n // Validate and resolve the verification method\n const publicJwk = await validateAndResolveVerificationMethod(agentContext, options.verificationMethod, [\n 'assertionMethod',\n ])\n\n // Validate the disclosure frame\n const disclosureFrame = options.disclosureFrame as DisclosureFrame<W3cV2JsonCredential> | undefined\n this.validateDisclosureFrame(disclosureFrame)\n\n publicJwk.alg = options.alg\n\n const sdJwt = new SDJwtInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n signer: getSdJwtSigner(agentContext, publicJwk),\n hashAlg: getSdJwtHashingAlgorithm(options.hashingAlgorithm),\n signAlg: options.alg,\n })\n\n // Sign SD-JWT\n const compact = await sdJwt.issue<W3cV2JsonCredential>(payload, disclosureFrame, {\n header: {\n typ: 'vc+sd-jwt',\n alg: options.alg,\n kid: options.verificationMethod,\n },\n })\n\n return W3cV2SdJwtVerifiableCredential.fromCompact(compact)\n }\n\n /**\n * Verifies the signature(s) of a credential\n *\n * @param credential the credential to be verified\n * @returns the verification result\n */\n public async verifyCredential(\n agentContext: AgentContext,\n options: W3cV2SdJwtVerifyCredentialOptions\n ): Promise<W3cV2VerifyCredentialResult> {\n const validationResults: W3cV2VerifyCredentialResult = {\n isValid: false,\n validations: {},\n }\n\n const sdJwt = new SDJwtInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n })\n\n try {\n let credential: W3cV2SdJwtVerifiableCredential\n try {\n // If instance is provided as input, we want to validate the credential\n // Otherwise, it is done by fromCompact below\n if (options.credential instanceof W3cV2SdJwtVerifiableCredential) {\n options.credential.validate()\n }\n\n credential =\n options.credential instanceof W3cV2SdJwtVerifiableCredential\n ? options.credential\n : W3cV2SdJwtVerifiableCredential.fromCompact(options.credential)\n\n // Validate JWT payload\n JwtPayload.fromJson(credential.sdJwt.payload).validate({\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n this.logCredentialShouldWarnings(agentContext, credential)\n\n validationResults.validations.dataModel = validateVc2ContextBaseline(credential.resolvedCredential.context)\n if (!validationResults.validations.dataModel.isValid) {\n return validationResults\n }\n\n validationResults.validations.dataModel = {\n isValid: true,\n }\n\n validationResults.validations.validityPeriod = validateVc2CredentialValidityPeriod({\n validFrom: credential.resolvedCredential.validFrom,\n validUntil: credential.resolvedCredential.validUntil,\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n validationResults.validations.credentialStatus = validateVc2CredentialStatus({\n credentialStatus: credential.resolvedCredential.credentialStatus,\n credentialFormat: 'SD-JWT',\n verifyCredentialStatus: options.verifyCredentialStatus,\n })\n } catch (error) {\n validationResults.validations.dataModel = {\n isValid: false,\n error,\n }\n\n return validationResults\n }\n\n const issuer = await getSignerForJwt(agentContext, credential, ['assertionMethod'])\n const issuerVerificationMethod = issuer.verificationMethod\n const issuerPublicKey = getPublicJwkFromVerificationMethod(issuerVerificationMethod)\n\n // Ensure the issuer is trusted according to the (optional) `getTrustedIssuersForVerification`\n // callback. For did-based issuers this is a no-op when no trusted issuers are configured,\n // preserving the previous \"trust any valid signature\" behavior. Throws when the issuer is not trusted.\n await TrustedIssuerContext.ensureTrustedCredentialSigner(\n agentContext,\n {\n signer: { method: 'did', didUrl: issuerVerificationMethod.id },\n verification: { type: 'credential', credential },\n },\n options.trustedIssuers\n )\n\n const holderBinding = parseHolderBindingFromCredential(credential.sdJwt.prettyClaims)\n const holder = holderBinding\n ? await extractKeyFromHolderBinding(agentContext, holderBinding, { didPurposes: ['authentication'] })\n : undefined\n\n setJwkAlgFromJwtHeader(issuerPublicKey, credential.sdJwt.header.alg)\n if (holder && credential.sdJwt.kbJwt) {\n setJwkAlgFromJwtHeader(holder.publicJwk, credential.sdJwt.kbJwt.header?.alg)\n }\n\n sdJwt.config({\n verifier: getSdJwtVerifier(agentContext, issuerPublicKey),\n kbVerifier: holder ? getSdJwtVerifier(agentContext, holder.publicJwk) : undefined,\n })\n\n try {\n await sdJwt.verify(credential.encoded, {\n skewSeconds: agentContext.config.validitySkewSeconds,\n keyBindingNonce: options.keyBinding?.nonce,\n expectedKeyBindingAudience: options.keyBinding?.audience,\n })\n\n validationResults.validations.signature = {\n isValid: true,\n }\n } catch (error) {\n validationResults.validations.signature = {\n isValid: false,\n error,\n }\n }\n\n validationResults.validations.issuerIsSigner = validateSignerIsExpectedParty(\n issuer,\n credential.resolvedCredential.issuerId,\n 'issuer'\n )\n\n validationResults.isValid = Object.values(validationResults.validations).every(\n (validation) => validation?.isValid === true\n )\n return validationResults\n } catch (error) {\n validationResults.error = error\n return validationResults\n }\n }\n\n /**\n * Signs a presentation including the credentials it includes\n *\n * @param presentation the presentation to be signed\n * @returns the signed presentation\n */\n public async signPresentation(\n agentContext: AgentContext,\n options: W3cV2SdJwtSignPresentationOptions\n ): Promise<W3cV2SdJwtVerifiablePresentation> {\n // Validate the instance\n MessageValidator.validateSync(options.presentation)\n\n // The JWT payload is simply the presentation\n const payload = JsonTransformer.toJSON(options.presentation) as W3cV2JsonPresentation\n\n // Add the nonce and aud to the payload\n payload.nonce = options.challenge\n payload.aud = options.domain\n\n const holder = await extractHolderFromPresentationCredentials(agentContext, options.presentation)\n\n holder.publicJwk.alg = holder.alg\n\n const sdJwt = new SDJwtInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n signer: getSdJwtSigner(agentContext, holder.publicJwk),\n hashAlg: getSdJwtHashingAlgorithm(options.hashingAlgorithm),\n signAlg: holder.alg,\n })\n\n // Validate the disclosure frame\n const disclosureFrame = options.disclosureFrame as DisclosureFrame<W3cV2JsonPresentation> | undefined\n this.validateDisclosureFrame(disclosureFrame)\n\n // Sign SD-JWT\n const compact = await sdJwt.issue<W3cV2JsonPresentation>(payload, disclosureFrame, {\n header: {\n typ: 'vp+sd-jwt',\n alg: holder.alg,\n kid: holder?.cnf?.kid,\n },\n })\n\n return W3cV2SdJwtVerifiablePresentation.fromCompact(compact)\n }\n\n /**\n * Verifies a presentation including the credentials it includes\n *\n * @param presentation the presentation to be verified\n * @returns the verification result\n */\n public async verifyPresentation(\n agentContext: AgentContext,\n options: W3cV2SdJwtVerifyPresentationOptions\n ): Promise<W3cV2VerifyPresentationResult> {\n const validationResults: W3cV2VerifyPresentationResult = {\n isValid: false,\n presentation: {\n isValid: false,\n validations: {},\n },\n credentialEntries: [],\n }\n\n const sdjwt = new SDJwtInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n })\n\n try {\n let presentation: W3cV2SdJwtVerifiablePresentation\n try {\n // If instance is provided as input, we want to validate the presentation\n if (options.presentation instanceof W3cV2SdJwtVerifiablePresentation) {\n options.presentation.validate()\n }\n\n presentation =\n options.presentation instanceof W3cV2SdJwtVerifiablePresentation\n ? options.presentation\n : W3cV2SdJwtVerifiablePresentation.fromCompact(options.presentation)\n\n // Validate JWT payload\n JwtPayload.fromJson(presentation.sdJwt.payload).validate({\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n this.logPresentationShouldWarnings(agentContext, presentation)\n\n // VC-JOSE-COSE: understood claims MUST be evaluated per verifier policy\n // https://www.w3.org/TR/vc-jose-cose/#validation-algorithm\n if (options.challenge !== presentation.sdJwt.prettyClaims.nonce) {\n throw new CredoError(`JWT payload 'nonce' does not match challenge '${options.challenge}'`)\n }\n\n const audArray = asArray(presentation.sdJwt.prettyClaims.aud)\n if (options.domain && !audArray.includes(options.domain)) {\n throw new CredoError(`JWT payload 'aud' does not include domain '${options.domain}'`)\n }\n\n const contextValidationResult = validateVc2ContextBaseline(presentation.resolvedPresentation.context)\n if (!contextValidationResult.isValid) {\n throw contextValidationResult.error\n }\n\n validationResults.presentation.validations.dataModel = {\n isValid: true,\n }\n } catch (error) {\n validationResults.presentation.validations.dataModel = {\n isValid: false,\n error,\n }\n\n return validationResults\n }\n\n const prover = await getSignerForJwt(agentContext, presentation, ['authentication'])\n const proverPublicKey = getPublicJwkFromVerificationMethod(prover.verificationMethod)\n const holderBinding = parseHolderBindingFromCredential(presentation.sdJwt.prettyClaims)\n const holder = holderBinding ? await extractKeyFromHolderBinding(agentContext, holderBinding) : undefined\n\n setJwkAlgFromJwtHeader(proverPublicKey, presentation.sdJwt.header.alg)\n if (holder && presentation.sdJwt.kbJwt) {\n setJwkAlgFromJwtHeader(holder.publicJwk, presentation.sdJwt.kbJwt.header?.alg)\n }\n\n sdjwt.config({\n verifier: getSdJwtVerifier(agentContext, proverPublicKey),\n kbVerifier: holder ? getSdJwtVerifier(agentContext, holder.publicJwk) : undefined,\n })\n\n try {\n await sdjwt.verify(presentation.encoded, {\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n validationResults.presentation.validations.presentationSignature = {\n isValid: true,\n }\n } catch (error) {\n validationResults.presentation.validations.presentationSignature = {\n isValid: false,\n error,\n }\n }\n\n validationResults.presentation.validations.holderIsSigner = validateSignerIsExpectedParty(\n prover,\n presentation.resolvedPresentation.holderId,\n 'holder'\n )\n\n validationResults.presentation.isValid = Object.values(validationResults.presentation.validations).every(\n (validation) => validation.isValid\n )\n\n // Credential-entry dispatch is orchestrated by W3cV2CredentialService.\n // This service verifies VP container integrity only.\n validationResults.isValid = validationResults.presentation.isValid\n\n return validationResults\n } catch (error) {\n validationResults.error = error\n return validationResults\n }\n }\n\n public async present(\n agentContext: AgentContext,\n options: W3cV2SdJwtVcPresentOptions\n ): Promise<W3cV2SdJwtVerifiableCredential> {\n const originalCompact =\n options.credential instanceof W3cV2SdJwtVerifiableCredential ? options.credential.encoded : options.credential\n\n const presentationFrame = options.presentationFrame as PresentationFrame<W3cV2JsonCredential>\n\n const sdjwt = new SDJwtInstance(this.getBaseSdJwtConfig(agentContext))\n const disclosedCompact = await sdjwt.present(originalCompact, presentationFrame)\n\n return W3cV2SdJwtVerifiableCredential.fromCompact(disclosedCompact)\n }\n\n /**\n * @deprecated use `applyDisclosuresForPaths` instead\n */\n public applyDisclosuresForPayload(\n compactSdJwtVc: string,\n requestedPayload: JsonObject\n ): W3cV2SdJwtVerifiableCredential {\n const sdJwt = applyDisclosuresForPayload(compactSdJwtVc, requestedPayload)\n return W3cV2SdJwtVerifiableCredential.fromCompact(sdJwt)\n }\n\n public applyDisclosuresForPaths(compactSdJwtVc: string, disclosedPaths: ClaimPath[]): W3cV2SdJwtVerifiableCredential {\n const { compact } = applyDisclosuresForPaths(compactSdJwtVc, disclosedPaths)\n return W3cV2SdJwtVerifiableCredential.fromCompact(compact)\n }\n\n private validateDisclosureFrame(disclosureFrame?: DisclosureFrame<W3cV2JsonCredential | W3cV2JsonPresentation>) {\n validateW3cV2SdJwtDisclosureFrame(disclosureFrame as IDisclosureFrame | undefined)\n }\n\n private getBaseSdJwtConfig(agentContext: AgentContext): SDJWTConfig {\n const kms = agentContext.resolve(KeyManagementApi)\n\n return {\n hasher: sdJwtVcHasher,\n saltGenerator: (length) => TypedArrayEncoder.toBase64Url(kms.randomBytes({ length })).slice(0, length),\n }\n }\n\n private logCredentialShouldWarnings(agentContext: AgentContext, credential: W3cV2SdJwtVerifiableCredential) {\n const payload = credential.sdJwt.prettyClaims\n const headerIss = credential.sdJwt.header.iss\n\n if (typeof headerIss === 'string' && typeof payload.iss === 'string' && headerIss !== payload.iss) {\n agentContext.config.logger.warn('VC-JOSE-COSE SHOULD warning: JOSE header iss conflicts with payload iss', {\n format: 'vc+sd-jwt',\n headerIss,\n payloadIss: payload.iss,\n })\n }\n\n if (\n typeof payload.jti === 'string' &&\n credential.resolvedCredential.id &&\n credential.resolvedCredential.id !== payload.jti\n ) {\n agentContext.config.logger.warn('VC-JOSE-COSE SHOULD warning: jti claim conflicts with credential id', {\n format: 'vc+sd-jwt',\n jti: payload.jti,\n credentialId: credential.resolvedCredential.id,\n })\n }\n\n if (typeof payload.sub === 'string' && !credential.resolvedCredential.credentialSubjectIds.includes(payload.sub)) {\n agentContext.config.logger.warn(\n 'VC-JOSE-COSE SHOULD warning: sub claim does not match any credentialSubject.id',\n {\n format: 'vc+sd-jwt',\n sub: payload.sub,\n credentialSubjectIds: credential.resolvedCredential.credentialSubjectIds,\n }\n )\n }\n }\n\n private logPresentationShouldWarnings(agentContext: AgentContext, presentation: W3cV2SdJwtVerifiablePresentation) {\n const payload = presentation.sdJwt.prettyClaims\n const headerIss = presentation.sdJwt.header.iss\n\n if (typeof headerIss === 'string' && typeof payload.iss === 'string' && headerIss !== payload.iss) {\n agentContext.config.logger.warn('VC-JOSE-COSE SHOULD warning: JOSE header iss conflicts with payload iss', {\n format: 'vp+sd-jwt',\n headerIss,\n payloadIss: payload.iss,\n })\n }\n\n if (\n typeof payload.jti === 'string' &&\n presentation.resolvedPresentation.id &&\n presentation.resolvedPresentation.id !== payload.jti\n ) {\n agentContext.config.logger.warn('VC-JOSE-COSE SHOULD warning: jti claim conflicts with presentation id', {\n format: 'vp+sd-jwt',\n jti: payload.jti,\n presentationId: presentation.resolvedPresentation.id,\n })\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@ import "../../sd-jwt-vc/index.mjs";
|
|
|
7
7
|
* @see https://www.w3.org/TR/vc-jose-cose/#securing-with-sd-jwt
|
|
8
8
|
* @see https://www.w3.org/TR/vc-jose-cose/#securing-vps-sd-jwt
|
|
9
9
|
*/
|
|
10
|
-
export declare const NON_DISCLOSEABLE_FIELDS: readonly ["@context", "type", "credentialStatus", "credentialSchema", "relatedResource"];
|
|
10
|
+
export declare const NON_DISCLOSEABLE_FIELDS: readonly ["@context", "type", "credentialStatus", "credentialSchema", "relatedResource", "cnf"];
|
|
11
11
|
/**
|
|
12
12
|
* Asserts that a disclosure frame does not make any of the {@link NON_DISCLOSEABLE_FIELDS} of a W3C
|
|
13
13
|
* VCDM 2.0 credential or presentation selectively disclosable.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"disclosureFrame.d.mts","names":[],"sources":["../../../../src/modules/vc/sd-jwt-vc/disclosureFrame.ts"],"mappings":";;;;;;;;;qBASa;;;;;;;;
|
|
1
|
+
{"version":3,"file":"disclosureFrame.d.mts","names":[],"sources":["../../../../src/modules/vc/sd-jwt-vc/disclosureFrame.ts"],"mappings":";;;;;;;;;qBASa;;;;;;;;wBAiBG,kCAAkC,kBAAkB"}
|
|
@@ -12,7 +12,8 @@ const NON_DISCLOSEABLE_FIELDS = [
|
|
|
12
12
|
"type",
|
|
13
13
|
"credentialStatus",
|
|
14
14
|
"credentialSchema",
|
|
15
|
-
"relatedResource"
|
|
15
|
+
"relatedResource",
|
|
16
|
+
"cnf"
|
|
16
17
|
];
|
|
17
18
|
/**
|
|
18
19
|
* Asserts that a disclosure frame does not make any of the {@link NON_DISCLOSEABLE_FIELDS} of a W3C
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"disclosureFrame.mjs","names":[],"sources":["../../../../src/modules/vc/sd-jwt-vc/disclosureFrame.ts"],"sourcesContent":["import { CredoError } from '../../../error'\nimport type { IDisclosureFrame } from '../../sd-jwt-vc'\n\n/**\n * List of fields that cannot be selectively disclosed.\n *\n * @see https://www.w3.org/TR/vc-jose-cose/#securing-with-sd-jwt\n * @see https://www.w3.org/TR/vc-jose-cose/#securing-vps-sd-jwt\n */\nexport const NON_DISCLOSEABLE_FIELDS = [\n '@context',\n 'type',\n 'credentialStatus',\n 'credentialSchema',\n 'relatedResource',\n] as const\n\n/**\n * Asserts that a disclosure frame does not make any of the {@link NON_DISCLOSEABLE_FIELDS} of a W3C\n * VCDM 2.0 credential or presentation selectively disclosable.\n *\n * Only the top level of the frame is checked. A nested claim that happens to share a name with a\n * non-discloseable field, such as `credentialSubject.type`, may be selectively disclosed.\n */\nexport function validateW3cV2SdJwtDisclosureFrame(disclosureFrame?: IDisclosureFrame) {\n if (!disclosureFrame) return\n\n for (const field of NON_DISCLOSEABLE_FIELDS) {\n if (disclosureFrame[field]) {\n throw new CredoError(`'${field}' property cannot be selectively disclosed`)\n }\n\n if (Array.isArray(disclosureFrame._sd) && disclosureFrame._sd.includes(field)) {\n throw new CredoError(`'${field}' property cannot be selectively disclosed`)\n }\n }\n}\n"],"mappings":";;;;;;;;;AASA,MAAa,0BAA0B;CACrC;CACA;CACA;CACA;CACA;AACF;;;;;;;;AASA,SAAgB,kCAAkC,iBAAoC;CACpF,IAAI,CAAC,iBAAiB;CAEtB,KAAK,MAAM,SAAS,yBAAyB;EAC3C,IAAI,gBAAgB,QAClB,MAAM,IAAI,WAAW,IAAI,MAAM,2CAA2C;EAG5E,IAAI,MAAM,QAAQ,gBAAgB,GAAG,KAAK,gBAAgB,IAAI,SAAS,KAAK,GAC1E,MAAM,IAAI,WAAW,IAAI,MAAM,2CAA2C;CAE9E;AACF"}
|
|
1
|
+
{"version":3,"file":"disclosureFrame.mjs","names":[],"sources":["../../../../src/modules/vc/sd-jwt-vc/disclosureFrame.ts"],"sourcesContent":["import { CredoError } from '../../../error'\nimport type { IDisclosureFrame } from '../../sd-jwt-vc'\n\n/**\n * List of fields that cannot be selectively disclosed.\n *\n * @see https://www.w3.org/TR/vc-jose-cose/#securing-with-sd-jwt\n * @see https://www.w3.org/TR/vc-jose-cose/#securing-vps-sd-jwt\n */\nexport const NON_DISCLOSEABLE_FIELDS = [\n '@context',\n 'type',\n 'credentialStatus',\n 'credentialSchema',\n 'relatedResource',\n // A verifier can't tell an omitted `cnf` disclosure from a credential without holder binding\n 'cnf',\n] as const\n\n/**\n * Asserts that a disclosure frame does not make any of the {@link NON_DISCLOSEABLE_FIELDS} of a W3C\n * VCDM 2.0 credential or presentation selectively disclosable.\n *\n * Only the top level of the frame is checked. A nested claim that happens to share a name with a\n * non-discloseable field, such as `credentialSubject.type`, may be selectively disclosed.\n */\nexport function validateW3cV2SdJwtDisclosureFrame(disclosureFrame?: IDisclosureFrame) {\n if (!disclosureFrame) return\n\n for (const field of NON_DISCLOSEABLE_FIELDS) {\n if (disclosureFrame[field]) {\n throw new CredoError(`'${field}' property cannot be selectively disclosed`)\n }\n\n if (Array.isArray(disclosureFrame._sd) && disclosureFrame._sd.includes(field)) {\n throw new CredoError(`'${field}' property cannot be selectively disclosed`)\n }\n }\n}\n"],"mappings":";;;;;;;;;AASA,MAAa,0BAA0B;CACrC;CACA;CACA;CACA;CACA;CAEA;AACF;;;;;;;;AASA,SAAgB,kCAAkC,iBAAoC;CACpF,IAAI,CAAC,iBAAiB;CAEtB,KAAK,MAAM,SAAS,yBAAyB;EAC3C,IAAI,gBAAgB,QAClB,MAAM,IAAI,WAAW,IAAI,MAAM,2CAA2C;EAG5E,IAAI,MAAM,QAAQ,gBAAgB,GAAG,KAAK,gBAAgB,IAAI,SAAS,KAAK,GAC1E,MAAM,IAAI,WAAW,IAAI,MAAM,2CAA2C;CAE9E;AACF"}
|
|
@@ -4,13 +4,12 @@ import { asArray } from "../../utils/array.mjs";
|
|
|
4
4
|
import { isDid } from "../../utils/did.mjs";
|
|
5
5
|
import "../../utils/index.mjs";
|
|
6
6
|
import "../../agent/index.mjs";
|
|
7
|
-
import { PublicJwk } from "../kms/jwk/PublicJwk.mjs";
|
|
8
7
|
import "../kms/index.mjs";
|
|
9
8
|
import { parseDid } from "../dids/domain/parse.mjs";
|
|
10
|
-
import { getPublicJwkFromVerificationMethod
|
|
11
|
-
import { DidResolverService } from "../dids/services/DidResolverService.mjs";
|
|
9
|
+
import { getPublicJwkFromVerificationMethod } from "../dids/domain/key-type/keyDidMapping.mjs";
|
|
12
10
|
import { DidsApi } from "../dids/DidsApi.mjs";
|
|
13
11
|
import "../dids/index.mjs";
|
|
12
|
+
import { resolveJwtSigner } from "./resolveSigner.mjs";
|
|
14
13
|
import { extractKeyFromHolderBinding, parseHolderBindingFromCredential } from "../sd-jwt-vc/utils.mjs";
|
|
15
14
|
import { W3cV2JwtVerifiableCredential } from "./jwt-vc/W3cV2JwtVerifiableCredential.mjs";
|
|
16
15
|
import { W3cV2SdJwtVerifiableCredential } from "./sd-jwt-vc/W3cV2SdJwtVerifiableCredential.mjs";
|
|
@@ -34,9 +33,18 @@ async function extractHolderFromPresentationCredentials(agentContext, presentati
|
|
|
34
33
|
if (holderDid) {
|
|
35
34
|
if (!isDid(holderDid)) throw new CredoError(`Presentation holder '${holderDid}' is not a valid did`);
|
|
36
35
|
const { didDocument, keys } = await agentContext.resolve(DidsApi).resolveCreatedDidDocumentWithKeys(holderDid);
|
|
37
|
-
|
|
36
|
+
let candidateMethods = didDocument.findVerificationMethodsByPurpose(["authentication"]).filter((method) => keys?.some(({ didDocumentRelativeKeyId }) => method.id.endsWith(didDocumentRelativeKeyId)));
|
|
38
37
|
if (candidateMethods.length === 0) throw new CredoError(`Unable to determine signer key for presentation holder '${holderDid}'. No locally controlled authentication verification method found.`);
|
|
39
|
-
if (candidateMethods.length > 1)
|
|
38
|
+
if (candidateMethods.length > 1) {
|
|
39
|
+
const credentialHolders = await getCredentialHolders(agentContext, credentials, { didPurposes: ["authentication"] });
|
|
40
|
+
const boundMethods = candidateMethods.filter((method) => {
|
|
41
|
+
const publicJwk = getPublicJwkFromVerificationMethod(method);
|
|
42
|
+
return credentialHolders.some((holder) => holder.publicJwk.equals(publicJwk));
|
|
43
|
+
});
|
|
44
|
+
if (boundMethods.length === 0) throw new CredoError(`Unable to deterministically resolve signer key for presentation holder '${holderDid}'. Multiple locally controlled authentication verification methods found, and the presentation credentials are not bound to any of them.`);
|
|
45
|
+
if (boundMethods.length > 1) throw new CredoError(`Unable to deterministically resolve signer key for presentation holder '${holderDid}'. Multiple locally controlled authentication verification methods found, and the presentation credentials are bound to more than one of them.`);
|
|
46
|
+
candidateMethods = boundMethods;
|
|
47
|
+
}
|
|
40
48
|
const selectedMethod = candidateMethods[0];
|
|
41
49
|
const publicJwk = getPublicJwkFromVerificationMethod(selectedMethod);
|
|
42
50
|
publicJwk.keyId = keys?.find(({ didDocumentRelativeKeyId }) => selectedMethod.id.endsWith(didDocumentRelativeKeyId))?.kmsKeyId ?? publicJwk.legacyKeyId;
|
|
@@ -48,7 +56,16 @@ async function extractHolderFromPresentationCredentials(agentContext, presentati
|
|
|
48
56
|
cnf: { kid: selectedMethod.id }
|
|
49
57
|
};
|
|
50
58
|
}
|
|
51
|
-
const
|
|
59
|
+
const credentialHolders = await getCredentialHolders(agentContext, credentials, { forSigning: true });
|
|
60
|
+
if (credentialHolders.length === 0) throw new CredoError("Unable to determine signer from presentation credentials, and presentation.holder is missing");
|
|
61
|
+
if (credentialHolders.length > 1) throw new CredoError("Unable to determine signer from presentation credentials. Multiple distinct holder bindings found and presentation.holder is missing.");
|
|
62
|
+
return credentialHolders[0];
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Returns the distinct keys that the credentials are bound to with `cnf`.
|
|
66
|
+
*/
|
|
67
|
+
async function getCredentialHolders(agentContext, credentials, options) {
|
|
68
|
+
const holders = /* @__PURE__ */ new Map();
|
|
52
69
|
for (const credential of credentials) {
|
|
53
70
|
if (!(credential instanceof W3cV2EnvelopedVerifiableCredential)) continue;
|
|
54
71
|
let claims;
|
|
@@ -57,60 +74,42 @@ async function extractHolderFromPresentationCredentials(agentContext, presentati
|
|
|
57
74
|
else continue;
|
|
58
75
|
const holderBinding = parseHolderBindingFromCredential(claims);
|
|
59
76
|
if (!holderBinding) continue;
|
|
60
|
-
|
|
77
|
+
const holder = await extractKeyFromHolderBinding(agentContext, holderBinding, options);
|
|
78
|
+
holders.set(holder.publicJwk.fingerprint, holder);
|
|
61
79
|
}
|
|
62
|
-
|
|
63
|
-
const uniqueFallbackHolders = new Map(fallbackHolders.map((holder) => [holder.publicJwk.fingerprint, holder]));
|
|
64
|
-
if (uniqueFallbackHolders.size > 1) throw new CredoError("Unable to determine signer from presentation credentials. Multiple distinct holder bindings found and presentation.holder is missing.");
|
|
65
|
-
return uniqueFallbackHolders.values().next().value;
|
|
80
|
+
return Array.from(holders.values());
|
|
66
81
|
}
|
|
67
82
|
/**
|
|
68
|
-
*
|
|
69
|
-
*
|
|
83
|
+
* Resolves the signer of a JWT credential or presentation. When no `iss` is present, the `issuer`
|
|
84
|
+
* of a credential or the `holder` of a presentation must be the signer.
|
|
70
85
|
*/
|
|
71
|
-
async function
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
verificationMethod = (await didResolver.resolveDidDocument(agentContext, iss)).dereferenceKey(`${iss}${kid}`, purpose);
|
|
97
|
-
} else if (kid && isDid(kid)) {
|
|
98
|
-
const didDocument = await didResolver.resolveDidDocument(agentContext, kid);
|
|
99
|
-
verificationMethod = didDocument.dereferenceKey(kid, purpose);
|
|
100
|
-
if (iss && didDocument.id !== iss) throw new CredoError(`kid '${kid}' does not match id of signer (holder/issuer) '${iss}'`);
|
|
101
|
-
} else {
|
|
102
|
-
if (!iss) throw new CredoError(`JWT 'iss' MUST be present in payload when no 'kid' is specified`);
|
|
103
|
-
const jwkClass = PublicJwk.supportedPublicJwkClassForSignatureAlgorithm(alg);
|
|
104
|
-
const supportedVerificationMethodTypes = getSupportedVerificationMethodTypesForPublicJwk(jwkClass);
|
|
105
|
-
const verificationMethods = (await didResolver.resolveDidDocument(agentContext, iss)).findVerificationMethodsByTypeAndPurpose(supportedVerificationMethodTypes, ["assertionMethod"]);
|
|
106
|
-
if (verificationMethods.length === 0) throw new CredoError(`No verification methods found for signer '${iss}' and key type '${jwkClass.name}' for alg '${alg}'. Unable to determine which public key is associated with the credential.`);
|
|
107
|
-
if (verificationMethods.length > 1) throw new CredoError(`Multiple verification methods found for signer '${iss}' and key type '${jwkClass.name}' for alg '${alg}'. Unable to determine which public key is associated with the credential.`);
|
|
108
|
-
verificationMethod = verificationMethods[0];
|
|
109
|
-
}
|
|
110
|
-
if (iss && verificationMethod.controller !== iss) throw new CredoError(`Verification method controller '${verificationMethod.controller}' does not match the signer '${iss}'`);
|
|
111
|
-
return verificationMethod;
|
|
86
|
+
async function getSignerForJwt(agentContext, credential, purpose) {
|
|
87
|
+
if (credential instanceof W3cV2JwtVerifiableCredential) return resolveJwtSigner(agentContext, {
|
|
88
|
+
alg: credential.jwt.header.alg,
|
|
89
|
+
kid: credential.jwt.header.kid,
|
|
90
|
+
iss: credential.jwt.payload.iss ?? credential.resolvedCredential.issuerId,
|
|
91
|
+
purpose
|
|
92
|
+
});
|
|
93
|
+
if (credential instanceof W3cV2JwtVerifiablePresentation) return resolveJwtSigner(agentContext, {
|
|
94
|
+
alg: credential.jwt.header.alg,
|
|
95
|
+
kid: credential.jwt.header.kid,
|
|
96
|
+
iss: credential.jwt.payload.iss ?? credential.resolvedPresentation.holderId,
|
|
97
|
+
purpose
|
|
98
|
+
});
|
|
99
|
+
if (credential instanceof W3cV2SdJwtVerifiableCredential) return resolveJwtSigner(agentContext, {
|
|
100
|
+
alg: credential.sdJwt.header.alg,
|
|
101
|
+
kid: credential.sdJwt.header.kid,
|
|
102
|
+
iss: credential.sdJwt.payload.iss ?? credential.resolvedCredential.issuerId,
|
|
103
|
+
purpose
|
|
104
|
+
});
|
|
105
|
+
return resolveJwtSigner(agentContext, {
|
|
106
|
+
alg: credential.sdJwt.header.alg,
|
|
107
|
+
kid: credential.sdJwt.header.kid,
|
|
108
|
+
iss: credential.sdJwt.payload.iss ?? credential.resolvedPresentation.holderId,
|
|
109
|
+
purpose
|
|
110
|
+
});
|
|
112
111
|
}
|
|
113
112
|
//#endregion
|
|
114
|
-
export { extractHolderFromPresentationCredentials,
|
|
113
|
+
export { extractHolderFromPresentationCredentials, getSignerForJwt, validateAndResolveVerificationMethod };
|
|
115
114
|
|
|
116
115
|
//# sourceMappingURL=v2-jwt-utils.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v2-jwt-utils.mjs","names":[],"sources":["../../../src/modules/vc/v2-jwt-utils.ts"],"sourcesContent":["import { AgentContext } from '../../agent'\nimport { CredoError } from '../../error'\nimport { asArray, isDid } from '../../utils'\nimport {\n type DidPurpose,\n DidResolverService,\n DidsApi,\n getPublicJwkFromVerificationMethod,\n parseDid,\n VerificationMethod,\n} from '../dids'\nimport { getSupportedVerificationMethodTypesForPublicJwk } from '../dids/domain/key-type/keyDidMapping'\nimport { type KnownJwaSignatureAlgorithm, PublicJwk } from '../kms'\nimport { extractKeyFromHolderBinding, parseHolderBindingFromCredential } from '../sd-jwt-vc/utils'\nimport { W3cV2JwtVerifiableCredential } from './jwt-vc/W3cV2JwtVerifiableCredential'\nimport { W3cV2JwtVerifiablePresentation } from './jwt-vc/W3cV2JwtVerifiablePresentation'\nimport { W3cV2EnvelopedVerifiableCredential } from './models/credential/W3cV2EnvelopedVerifiableCredential'\nimport type { W3cV2Presentation } from './models/presentation/W3cV2Presentation'\nimport { W3cV2SdJwtVerifiableCredential } from './sd-jwt-vc/W3cV2SdJwtVerifiableCredential'\nimport { W3cV2SdJwtVerifiablePresentation } from './sd-jwt-vc/W3cV2SdJwtVerifiablePresentation'\n\nexport async function validateAndResolveVerificationMethod(\n agentContext: AgentContext,\n verificationMethod: string,\n allowsPurposes?: DidPurpose[]\n) {\n if (!isDid(verificationMethod)) {\n throw new CredoError('Only did identifiers are supported as verification method')\n }\n\n const parsedDid = parseDid(verificationMethod)\n if (!parsedDid.fragment) {\n throw new CredoError(`didUrl '${parsedDid.didUrl}' does not contain a '#'. Unable to derive key from did document`)\n }\n\n const dids = agentContext.resolve(DidsApi)\n const { didDocument, keys } = await dids.resolveCreatedDidDocumentWithKeys(parsedDid.did)\n const verificationMethodObject = didDocument.dereferenceKey(verificationMethod, allowsPurposes)\n const publicJwk = getPublicJwkFromVerificationMethod(verificationMethodObject)\n\n publicJwk.keyId =\n keys?.find(({ didDocumentRelativeKeyId }) => verificationMethodObject.id.endsWith(didDocumentRelativeKeyId))\n ?.kmsKeyId ?? publicJwk.legacyKeyId\n\n return publicJwk\n}\n\nexport async function extractHolderFromPresentationCredentials(\n agentContext: AgentContext,\n presentation: W3cV2Presentation\n) {\n const credentials = asArray(presentation.verifiableCredential)\n\n const holderDid = presentation.holderId\n if (holderDid) {\n if (!isDid(holderDid)) {\n throw new CredoError(`Presentation holder '${holderDid}' is not a valid did`)\n }\n\n const dids = agentContext.resolve(DidsApi)\n const { didDocument, keys } = await dids.resolveCreatedDidDocumentWithKeys(holderDid)\n\n const authenticationMethods = didDocument.findVerificationMethodsByPurpose(['authentication'])\n\n const candidateMethods = authenticationMethods.filter((method) =>\n keys?.some(({ didDocumentRelativeKeyId }) => method.id.endsWith(didDocumentRelativeKeyId))\n )\n\n if (candidateMethods.length === 0) {\n throw new CredoError(\n `Unable to determine signer key for presentation holder '${holderDid}'. No locally controlled authentication verification method found.`\n )\n }\n\n if (candidateMethods.length > 1) {\n throw new CredoError(\n `Unable to deterministically resolve signer key for presentation holder '${holderDid}'. Multiple locally controlled authentication verification methods found.`\n )\n }\n\n const selectedMethod = candidateMethods[0]\n const publicJwk = getPublicJwkFromVerificationMethod(selectedMethod)\n publicJwk.keyId =\n keys?.find(({ didDocumentRelativeKeyId }) => selectedMethod.id.endsWith(didDocumentRelativeKeyId))?.kmsKeyId ??\n publicJwk.legacyKeyId\n\n const [alg] = publicJwk.supportedSignatureAlgorithms\n if (!alg) {\n throw new CredoError(\n `No supported JWA signature algorithms found for holder verification method '${selectedMethod.id}'`\n )\n }\n\n return {\n alg,\n publicJwk,\n cnf: {\n kid: selectedMethod.id,\n },\n }\n }\n\n const fallbackHolders: Array<Awaited<ReturnType<typeof extractKeyFromHolderBinding>>> = []\n\n for (const credential of credentials) {\n if (!(credential instanceof W3cV2EnvelopedVerifiableCredential)) continue\n\n let claims: Record<string, unknown>\n if (credential.envelopedCredential instanceof W3cV2SdJwtVerifiableCredential) {\n claims = credential.envelopedCredential.sdJwt.prettyClaims\n } else if (credential.envelopedCredential instanceof W3cV2JwtVerifiableCredential) {\n claims = credential.envelopedCredential.jwt.payload.toJson()\n } else {\n continue\n }\n\n const holderBinding = parseHolderBindingFromCredential(claims)\n if (!holderBinding) continue\n\n fallbackHolders.push(await extractKeyFromHolderBinding(agentContext, holderBinding, { forSigning: true }))\n }\n\n if (fallbackHolders.length === 0) {\n throw new CredoError('Unable to determine signer from presentation credentials, and presentation.holder is missing')\n }\n\n const uniqueFallbackHolders = new Map(fallbackHolders.map((holder) => [holder.publicJwk.fingerprint, holder]))\n if (uniqueFallbackHolders.size > 1) {\n throw new CredoError(\n 'Unable to determine signer from presentation credentials. Multiple distinct holder bindings found and presentation.holder is missing.'\n )\n }\n\n return uniqueFallbackHolders.values().next().value as Awaited<ReturnType<typeof extractKeyFromHolderBinding>>\n}\n\n/**\n * This method tries to find the verification method associated with the JWT credential or presentation.\n * This verification method can then be used to verify the credential or presentation signature.\n */\nexport async function getVerificationMethodForJwt(\n agentContext: AgentContext,\n credential:\n | W3cV2JwtVerifiableCredential\n | W3cV2JwtVerifiablePresentation\n | W3cV2SdJwtVerifiableCredential\n | W3cV2SdJwtVerifiablePresentation,\n purpose?: DidPurpose[]\n) {\n let alg: KnownJwaSignatureAlgorithm\n let kid: string | undefined\n let iss: string | undefined\n\n // Determine the algorithm, kid and iss based on the type of credential / presentation\n if (credential instanceof W3cV2JwtVerifiableCredential) {\n alg = credential.jwt.header.alg as KnownJwaSignatureAlgorithm\n kid = credential.jwt.header.kid\n iss = credential.jwt.payload.iss ?? credential.resolvedCredential.issuerId\n } else if (credential instanceof W3cV2JwtVerifiablePresentation) {\n alg = credential.jwt.header.alg as KnownJwaSignatureAlgorithm\n kid = credential.jwt.header.kid\n iss = credential.jwt.payload.iss ?? credential.resolvedPresentation.holderId\n } else if (credential instanceof W3cV2SdJwtVerifiableCredential) {\n alg = credential.sdJwt.header.alg as KnownJwaSignatureAlgorithm\n kid = credential.sdJwt.header.kid\n iss = credential.sdJwt.payload.iss ?? credential.resolvedCredential.issuerId\n } else {\n alg = credential.sdJwt.header.alg as KnownJwaSignatureAlgorithm\n kid = credential.sdJwt.header.kid\n iss = credential.sdJwt.payload.iss ?? credential.resolvedPresentation.holderId\n }\n\n const didResolver = agentContext.dependencyManager.resolve(DidResolverService)\n let verificationMethod: VerificationMethod\n\n // If the kid starts with # we assume it is a relative did url, and we resolve\n //it based on the `iss` and the `kid`\n if (kid?.startsWith('#')) {\n if (!iss || !isDid(iss)) {\n throw new CredoError(`JWT 'iss' MUST be a did when 'kid' is a relative did url`)\n }\n\n const didDocument = await didResolver.resolveDidDocument(agentContext, iss)\n verificationMethod = didDocument.dereferenceKey(`${iss}${kid}`, purpose)\n } else if (kid && isDid(kid)) {\n const didDocument = await didResolver.resolveDidDocument(agentContext, kid)\n verificationMethod = didDocument.dereferenceKey(kid, purpose)\n\n if (iss && didDocument.id !== iss) {\n throw new CredoError(`kid '${kid}' does not match id of signer (holder/issuer) '${iss}'`)\n }\n } else {\n if (!iss) {\n throw new CredoError(`JWT 'iss' MUST be present in payload when no 'kid' is specified`)\n }\n\n // Find the verificationMethod in the did document based on the alg and proofPurpose\n const jwkClass = PublicJwk.supportedPublicJwkClassForSignatureAlgorithm(alg)\n const supportedVerificationMethodTypes = getSupportedVerificationMethodTypesForPublicJwk(jwkClass)\n\n const didDocument = await didResolver.resolveDidDocument(agentContext, iss)\n const verificationMethods = didDocument.findVerificationMethodsByTypeAndPurpose(supportedVerificationMethodTypes, [\n 'assertionMethod',\n ])\n\n if (verificationMethods.length === 0) {\n throw new CredoError(\n `No verification methods found for signer '${iss}' and key type '${jwkClass.name}' for alg '${alg}'. Unable to determine which public key is associated with the credential.`\n )\n }\n if (verificationMethods.length > 1) {\n throw new CredoError(\n `Multiple verification methods found for signer '${iss}' and key type '${jwkClass.name}' for alg '${alg}'. Unable to determine which public key is associated with the credential.`\n )\n }\n\n verificationMethod = verificationMethods[0]\n }\n\n // Verify the controller of the verificationMethod matches the signer of the credential\n if (iss && verificationMethod.controller !== iss) {\n throw new CredoError(\n `Verification method controller '${verificationMethod.controller}' does not match the signer '${iss}'`\n )\n }\n\n return verificationMethod\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"v2-jwt-utils.mjs","names":[],"sources":["../../../src/modules/vc/v2-jwt-utils.ts"],"sourcesContent":["import { AgentContext } from '../../agent'\nimport { CredoError } from '../../error'\nimport { asArray, isDid } from '../../utils'\nimport { type DidPurpose, DidsApi, getPublicJwkFromVerificationMethod, parseDid } from '../dids'\nimport { type KnownJwaSignatureAlgorithm } from '../kms'\nimport { extractKeyFromHolderBinding, parseHolderBindingFromCredential } from '../sd-jwt-vc/utils'\nimport { W3cV2JwtVerifiableCredential } from './jwt-vc/W3cV2JwtVerifiableCredential'\nimport { W3cV2JwtVerifiablePresentation } from './jwt-vc/W3cV2JwtVerifiablePresentation'\nimport { W3cV2EnvelopedVerifiableCredential } from './models/credential/W3cV2EnvelopedVerifiableCredential'\nimport type { W3cV2Presentation, W3cV2PresentationCredentialEntry } from './models/presentation/W3cV2Presentation'\nimport { resolveJwtSigner } from './resolveSigner'\nimport { W3cV2SdJwtVerifiableCredential } from './sd-jwt-vc/W3cV2SdJwtVerifiableCredential'\nimport { W3cV2SdJwtVerifiablePresentation } from './sd-jwt-vc/W3cV2SdJwtVerifiablePresentation'\n\nexport async function validateAndResolveVerificationMethod(\n agentContext: AgentContext,\n verificationMethod: string,\n allowsPurposes?: DidPurpose[]\n) {\n if (!isDid(verificationMethod)) {\n throw new CredoError('Only did identifiers are supported as verification method')\n }\n\n const parsedDid = parseDid(verificationMethod)\n if (!parsedDid.fragment) {\n throw new CredoError(`didUrl '${parsedDid.didUrl}' does not contain a '#'. Unable to derive key from did document`)\n }\n\n const dids = agentContext.resolve(DidsApi)\n const { didDocument, keys } = await dids.resolveCreatedDidDocumentWithKeys(parsedDid.did)\n const verificationMethodObject = didDocument.dereferenceKey(verificationMethod, allowsPurposes)\n const publicJwk = getPublicJwkFromVerificationMethod(verificationMethodObject)\n\n publicJwk.keyId =\n keys?.find(({ didDocumentRelativeKeyId }) => verificationMethodObject.id.endsWith(didDocumentRelativeKeyId))\n ?.kmsKeyId ?? publicJwk.legacyKeyId\n\n return publicJwk\n}\n\nexport async function extractHolderFromPresentationCredentials(\n agentContext: AgentContext,\n presentation: W3cV2Presentation\n) {\n const credentials = asArray(presentation.verifiableCredential)\n\n const holderDid = presentation.holderId\n if (holderDid) {\n if (!isDid(holderDid)) {\n throw new CredoError(`Presentation holder '${holderDid}' is not a valid did`)\n }\n\n const dids = agentContext.resolve(DidsApi)\n const { didDocument, keys } = await dids.resolveCreatedDidDocumentWithKeys(holderDid)\n\n const authenticationMethods = didDocument.findVerificationMethodsByPurpose(['authentication'])\n\n let candidateMethods = authenticationMethods.filter((method) =>\n keys?.some(({ didDocumentRelativeKeyId }) => method.id.endsWith(didDocumentRelativeKeyId))\n )\n\n if (candidateMethods.length === 0) {\n throw new CredoError(\n `Unable to determine signer key for presentation holder '${holderDid}'. No locally controlled authentication verification method found.`\n )\n }\n\n if (candidateMethods.length > 1) {\n // Pick the key the credentials are bound to\n const credentialHolders = await getCredentialHolders(agentContext, credentials, {\n didPurposes: ['authentication'],\n })\n const boundMethods = candidateMethods.filter((method) => {\n const publicJwk = getPublicJwkFromVerificationMethod(method)\n return credentialHolders.some((holder) => holder.publicJwk.equals(publicJwk))\n })\n\n if (boundMethods.length === 0) {\n throw new CredoError(\n `Unable to deterministically resolve signer key for presentation holder '${holderDid}'. Multiple locally controlled authentication verification methods found, and the presentation credentials are not bound to any of them.`\n )\n }\n\n if (boundMethods.length > 1) {\n throw new CredoError(\n `Unable to deterministically resolve signer key for presentation holder '${holderDid}'. Multiple locally controlled authentication verification methods found, and the presentation credentials are bound to more than one of them.`\n )\n }\n\n candidateMethods = boundMethods\n }\n\n const selectedMethod = candidateMethods[0]\n const publicJwk = getPublicJwkFromVerificationMethod(selectedMethod)\n publicJwk.keyId =\n keys?.find(({ didDocumentRelativeKeyId }) => selectedMethod.id.endsWith(didDocumentRelativeKeyId))?.kmsKeyId ??\n publicJwk.legacyKeyId\n\n const [alg] = publicJwk.supportedSignatureAlgorithms\n if (!alg) {\n throw new CredoError(\n `No supported JWA signature algorithms found for holder verification method '${selectedMethod.id}'`\n )\n }\n\n return {\n alg,\n publicJwk,\n cnf: {\n kid: selectedMethod.id,\n },\n }\n }\n\n const credentialHolders = await getCredentialHolders(agentContext, credentials, { forSigning: true })\n if (credentialHolders.length === 0) {\n throw new CredoError('Unable to determine signer from presentation credentials, and presentation.holder is missing')\n }\n\n if (credentialHolders.length > 1) {\n throw new CredoError(\n 'Unable to determine signer from presentation credentials. Multiple distinct holder bindings found and presentation.holder is missing.'\n )\n }\n\n return credentialHolders[0]\n}\n\n/**\n * Returns the distinct keys that the credentials are bound to with `cnf`.\n */\nasync function getCredentialHolders(\n agentContext: AgentContext,\n credentials: W3cV2PresentationCredentialEntry[],\n options: Parameters<typeof extractKeyFromHolderBinding>[2]\n) {\n const holders = new Map<string, Awaited<ReturnType<typeof extractKeyFromHolderBinding>>>()\n\n for (const credential of credentials) {\n if (!(credential instanceof W3cV2EnvelopedVerifiableCredential)) continue\n\n let claims: Record<string, unknown>\n if (credential.envelopedCredential instanceof W3cV2SdJwtVerifiableCredential) {\n claims = credential.envelopedCredential.sdJwt.prettyClaims\n } else if (credential.envelopedCredential instanceof W3cV2JwtVerifiableCredential) {\n claims = credential.envelopedCredential.jwt.payload.toJson()\n } else {\n continue\n }\n\n const holderBinding = parseHolderBindingFromCredential(claims)\n if (!holderBinding) continue\n\n const holder = await extractKeyFromHolderBinding(agentContext, holderBinding, options)\n holders.set(holder.publicJwk.fingerprint, holder)\n }\n\n return Array.from(holders.values())\n}\n\n/**\n * Resolves the signer of a JWT credential or presentation. When no `iss` is present, the `issuer`\n * of a credential or the `holder` of a presentation must be the signer.\n */\nexport async function getSignerForJwt(\n agentContext: AgentContext,\n credential:\n | W3cV2JwtVerifiableCredential\n | W3cV2JwtVerifiablePresentation\n | W3cV2SdJwtVerifiableCredential\n | W3cV2SdJwtVerifiablePresentation,\n purpose: DidPurpose[]\n) {\n if (credential instanceof W3cV2JwtVerifiableCredential) {\n return resolveJwtSigner(agentContext, {\n alg: credential.jwt.header.alg as KnownJwaSignatureAlgorithm,\n kid: credential.jwt.header.kid,\n iss: credential.jwt.payload.iss ?? credential.resolvedCredential.issuerId,\n purpose,\n })\n }\n if (credential instanceof W3cV2JwtVerifiablePresentation) {\n return resolveJwtSigner(agentContext, {\n alg: credential.jwt.header.alg as KnownJwaSignatureAlgorithm,\n kid: credential.jwt.header.kid,\n iss: credential.jwt.payload.iss ?? credential.resolvedPresentation.holderId,\n purpose,\n })\n }\n if (credential instanceof W3cV2SdJwtVerifiableCredential) {\n return resolveJwtSigner(agentContext, {\n alg: credential.sdJwt.header.alg as KnownJwaSignatureAlgorithm,\n kid: credential.sdJwt.header.kid,\n iss: credential.sdJwt.payload.iss ?? credential.resolvedCredential.issuerId,\n purpose,\n })\n }\n return resolveJwtSigner(agentContext, {\n alg: credential.sdJwt.header.alg as KnownJwaSignatureAlgorithm,\n kid: credential.sdJwt.header.kid,\n iss: credential.sdJwt.payload.iss ?? credential.resolvedPresentation.holderId,\n purpose,\n })\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { X509Certificate } from "./X509Certificate.mjs";
|
|
2
|
-
import { X509RevocationCheckOptions } from "./X509ValidationOptions.mjs";
|
|
2
|
+
import { X509RevocationCheckOptions, X509RevocationCheckOptionsWithDefaults } from "./X509ValidationOptions.mjs";
|
|
3
3
|
import { SdJwtVc } from "../sd-jwt-vc/SdJwtVcService.mjs";
|
|
4
4
|
import { JwtPayload } from "../../crypto/jose/jwt/JwtPayload.mjs";
|
|
5
5
|
import { W3cJwtVerifiableCredential } from "../vc/jwt-vc/W3cJwtVerifiableCredential.mjs";
|
|
@@ -100,17 +100,9 @@ export interface X509ModuleConfigOptions {
|
|
|
100
100
|
*/
|
|
101
101
|
getTrustedCertificatesForVerification?(agentContext: AgentContext, verificationContext: X509VerificationContext): Promise<string[] | undefined | X509VerificationTrustedCertificates[]> | string[] | X509VerificationTrustedCertificates[] | undefined;
|
|
102
102
|
/**
|
|
103
|
-
* Configuration for certificate revocation checking
|
|
104
|
-
* @
|
|
105
|
-
*
|
|
106
|
-
* {
|
|
107
|
-
* mode: X509RevocationCheckMode.SoftFail, // do not fail on network error
|
|
108
|
-
* checkFullChain: true, // check the leaf and all intermediate CAs
|
|
109
|
-
* timeoutMs: 5000, // 5 seconds
|
|
110
|
-
* maxCrlSizeBytes: 10485760, // 10MB
|
|
111
|
-
* crlCacheExpirySeconds: 3600 // 1 hour
|
|
112
|
-
* }
|
|
113
|
-
* ```
|
|
103
|
+
* Configuration for certificate revocation checking. Options that are not set use
|
|
104
|
+
* {@link defaultX509RevocationCheckOptions}: `SoftFail` (do not fail on network error) for the
|
|
105
|
+
* leaf and all intermediate CAs, a 5 second timeout, a 10 MB CRL size limit and a 1 hour cache.
|
|
114
106
|
*/
|
|
115
107
|
revocationCheck?: X509RevocationCheckOptions;
|
|
116
108
|
}
|
|
@@ -126,7 +118,7 @@ export declare class X509ModuleConfig {
|
|
|
126
118
|
* @deprecated use the global `getTrustedIssuersForVerification` instead
|
|
127
119
|
*/
|
|
128
120
|
setTrustedCertificatesForVerification(fn: X509ModuleConfigOptions['getTrustedCertificatesForVerification']): void;
|
|
129
|
-
get revocationCheck():
|
|
121
|
+
get revocationCheck(): X509RevocationCheckOptionsWithDefaults;
|
|
130
122
|
setRevocationCheck(options?: X509RevocationCheckOptions): void;
|
|
131
123
|
setTrustedCertificates(trustedCertificates?: Array<string | X509Certificate>): void;
|
|
132
124
|
addTrustedCertificate(trustedCertificate: string | X509Certificate): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"X509ModuleConfig.d.mts","names":[],"sources":["../../../src/modules/x509/X509ModuleConfig.ts"],"mappings":";;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"X509ModuleConfig.d.mts","names":[],"sources":["../../../src/modules/x509/X509ModuleConfig.ts"],"mappings":";;;;;;;;;;YAcY;EACV;EACA;;YAGU;EACV;EACA,YAAY,UAAU,OAAO,6BAA6B;;;;EAK1D;;;;EAKA;;;;;;;;;YAUU,qCAAqC;YAKrC;EACV;EACA;IACE;IACA,SAAS;;;YAID;EACV;;;;;EAOA;EAGA;IACE;IACA,SAAS;;;YAID;EACV;EAGA;IACE;IACA,SAAS;;;YAID;EACV;;;;;EAOA;EAGA;IACE;IACA,SAAS;;;iBAII;;;;;;;;EAQf,kBAAkB;EAElB,cACI,iCACA,qCACA,wDACA,8CACA,+CACA;;iBAGW;;;;;EAKf,sBAAsB,eAAe;;;;;;;;;;;;EAarC,uCACE,cAAc,cACd,qBAAqB,0BAEnB,+BAA+B,oDAE/B;;;;;;EAQJ,kBAAkB;;qBAGP;;EAKQ,YAAA,UAAU;MAUlB;;;;MASA,2CAAqC,cAxChC,cAAY,qBACL,4BAEnB,+BAA+B,oDAE/B;;;;EA0CG,sCAAsC,IAAI;MAItC,mBAAmB;EAIvB,mBAAmB,UAAU;EAI7B,uBAAuB,sBAAsB,eAAe;EAS5D,sBAAsB,6BAA6B"}
|
|
@@ -2,6 +2,7 @@ import _classPrivateFieldInitSpec from "../../_virtual/_@oxc-project_runtime@0.1
|
|
|
2
2
|
import _classPrivateFieldGet2 from "../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/classPrivateFieldGet2.mjs";
|
|
3
3
|
import _classPrivateFieldSet2 from "../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/classPrivateFieldSet2.mjs";
|
|
4
4
|
import { X509Certificate } from "./X509Certificate.mjs";
|
|
5
|
+
import { withX509RevocationCheckDefaults } from "./X509ValidationOptions.mjs";
|
|
5
6
|
//#region src/modules/x509/X509ModuleConfig.ts
|
|
6
7
|
var _trustedCertificates = /* @__PURE__ */ new WeakMap();
|
|
7
8
|
var _getTrustedCertificatesForVerification = /* @__PURE__ */ new WeakMap();
|
|
@@ -31,7 +32,7 @@ var X509ModuleConfig = class {
|
|
|
31
32
|
_classPrivateFieldSet2(_getTrustedCertificatesForVerification, this, fn);
|
|
32
33
|
}
|
|
33
34
|
get revocationCheck() {
|
|
34
|
-
return _classPrivateFieldGet2(_revocationCheck, this);
|
|
35
|
+
return withX509RevocationCheckDefaults(_classPrivateFieldGet2(_revocationCheck, this));
|
|
35
36
|
}
|
|
36
37
|
setRevocationCheck(options) {
|
|
37
38
|
_classPrivateFieldSet2(_revocationCheck, this, options);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"X509ModuleConfig.mjs","names":[],"sources":["../../../src/modules/x509/X509ModuleConfig.ts"],"sourcesContent":["import type { AgentContext } from '../../agent/context/AgentContext'\nimport type { VerificationTypeMdocReaderAuth } from '../../agent/TrustedIssuersForVerification'\nimport type { JwtPayload } from '../../crypto/jose/jwt/JwtPayload'\nimport type { Mdoc } from '../mdoc/Mdoc'\nimport type { SdJwtVc } from '../sd-jwt-vc/SdJwtVcService'\nimport type { W3cJwtVerifiableCredential } from '../vc/jwt-vc/W3cJwtVerifiableCredential'\nimport type { W3cJwtVerifiablePresentation } from '../vc/jwt-vc/W3cJwtVerifiablePresentation'\nimport { X509Certificate } from './X509Certificate'\nimport {
|
|
1
|
+
{"version":3,"file":"X509ModuleConfig.mjs","names":[],"sources":["../../../src/modules/x509/X509ModuleConfig.ts"],"sourcesContent":["import type { AgentContext } from '../../agent/context/AgentContext'\nimport type { VerificationTypeMdocReaderAuth } from '../../agent/TrustedIssuersForVerification'\nimport type { JwtPayload } from '../../crypto/jose/jwt/JwtPayload'\nimport type { Mdoc } from '../mdoc/Mdoc'\nimport type { SdJwtVc } from '../sd-jwt-vc/SdJwtVcService'\nimport type { W3cJwtVerifiableCredential } from '../vc/jwt-vc/W3cJwtVerifiableCredential'\nimport type { W3cJwtVerifiablePresentation } from '../vc/jwt-vc/W3cJwtVerifiablePresentation'\nimport { X509Certificate } from './X509Certificate'\nimport {\n withX509RevocationCheckDefaults,\n type X509RevocationCheckOptions,\n type X509RevocationCheckOptionsWithDefaults,\n} from './X509ValidationOptions'\n\nexport type X509VerificationTrustedCertificates = {\n issuance: string[]\n status?: string[]\n}\n\nexport type X509VerificationTypeCredential = {\n type: 'credential'\n credential: SdJwtVc | Mdoc | W3cJwtVerifiableCredential | W3cJwtVerifiablePresentation\n\n /**\n * The `id` of the `DidCommProofRecord` that this verification is bound to.\n */\n didcommProofRecordId?: string\n\n /**\n * The `id` of the `OpenId4VcVerificationSessionRecord` that this verification is bound to.\n */\n openId4VcVerificationSessionId?: string\n}\n\n/**\n * Reader authentication on an incoming mdoc request.\n *\n * There is no separate legacy shape for this verification type: reader authentication is only\n * resolved on the DC API paths that were added after this callback was deprecated, so the type of\n * the `getTrustedIssuersForVerification` callback is reused as-is.\n */\nexport type X509VerificationTypeMdocReaderAuth = VerificationTypeMdocReaderAuth\n\n// NOTE: we should probably move these to the OpenID4VC module\n// but have to think about the typing. Probably the base interface should just contain\n// the `verification` with a `type`. And extension modules can extend the verification\nexport type X509VerificationTypeOauth2SecuredAuthorizationRequest = {\n type: 'oauth2SecuredAuthorizationRequest'\n authorizationRequest: {\n jwt: string\n payload: JwtPayload\n }\n}\n\nexport type X509VerificationTypeOpenId4VciKeyAttestation = {\n type: 'openId4VciKeyAttestation'\n\n /**\n * The `id` of the `OpenId4VcIssuanceSessionRecord` that this key\n * attestation verification is bound to.\n */\n // TODO: should be the record, but we don't have access to the record type here.\n openId4VcIssuanceSessionId: string\n\n // NOTE: it would be more helpful to have the typed JWT payload from openid4vc here?\n keyAttestation: {\n jwt: string\n payload: JwtPayload\n }\n}\n\nexport type X509VerificationTypeOpenId4VciCredentialIssuerMetadata = {\n type: 'openId4VciCredentialIssuerMetadata'\n\n // NOTE: it would be more helpful to have the typed JWT payload from openid4vc here?\n credentialIssuerMetadata: {\n jwt: string\n payload: JwtPayload\n }\n}\n\nexport type X509VerificationTypeOauth2ClientAttestation = {\n type: 'oauth2ClientAttestation'\n\n /**\n * The `id` of the `OpenId4VcIssuanceSessionRecord` that this client\n * attestation verification is bound to.\n */\n // TODO: should be the record, but we don't have access to the record type here.\n openId4VcIssuanceSessionId: string\n\n // NOTE: it would be more helpful to have the typed JWT payload from openid4vc here?\n clientAttestation: {\n jwt: string\n payload: JwtPayload\n }\n}\n\nexport interface X509VerificationContext {\n /**\n * The certificate chain provided with the data to be verified. The trusted certificates\n * are determined before verification and thus it is not verified that the data was actually\n * signed by the private key associated with the leaf certificate in the certificate chain, or\n * whether the certificate chain is valid. However if the certificate\n * does not match, or is not valid, verification will always fail at a later stage\n */\n certificateChain: X509Certificate[]\n\n verification:\n | X509VerificationTypeCredential\n | X509VerificationTypeMdocReaderAuth\n | X509VerificationTypeOauth2SecuredAuthorizationRequest\n | X509VerificationTypeOauth2ClientAttestation\n | X509VerificationTypeOpenId4VciKeyAttestation\n | X509VerificationTypeOpenId4VciCredentialIssuerMetadata\n}\n\nexport interface X509ModuleConfigOptions {\n /**\n *\n * Array of trusted base64-encoded certificate strings in the DER-format.\n */\n trustedCertificates?: Array<string | X509Certificate>\n\n /**\n * Optional callback method that will be called to dynamically get trusted certificates for a verification.\n * It will provide the `agentContext` and `verificationContext` allowing to dynamically set the trusted certificates\n * for a tenant or verification context.\n *\n * If no certificates should be trusted an empty array should be returned. If `undefined` is returned\n * it will fallback to the globally registered trusted certificates\n *\n * @deprecated use the global `getTrustedIssuersForVerification` instead\n * @returns An array of base64-encoded certificate strings or PEM certificate strings.\n */\n getTrustedCertificatesForVerification?(\n agentContext: AgentContext,\n verificationContext: X509VerificationContext\n ):\n | Promise<string[] | undefined | X509VerificationTrustedCertificates[]>\n | string[]\n | X509VerificationTrustedCertificates[]\n | undefined\n\n /**\n * Configuration for certificate revocation checking. Options that are not set use\n * {@link defaultX509RevocationCheckOptions}: `SoftFail` (do not fail on network error) for the\n * leaf and all intermediate CAs, a 5 second timeout, a 10 MB CRL size limit and a 1 hour cache.\n */\n revocationCheck?: X509RevocationCheckOptions\n}\n\nexport class X509ModuleConfig {\n #trustedCertificates?: X509Certificate[]\n #getTrustedCertificatesForVerification?: X509ModuleConfigOptions['getTrustedCertificatesForVerification']\n #revocationCheck?: X509RevocationCheckOptions\n\n public constructor(options?: X509ModuleConfigOptions) {\n this.setTrustedCertificates(options?.trustedCertificates)\n if (options?.getTrustedCertificatesForVerification) {\n this.setTrustedCertificatesForVerification(options.getTrustedCertificatesForVerification)\n }\n if (options?.revocationCheck) {\n this.#revocationCheck = options.revocationCheck\n }\n }\n\n public get trustedCertificates() {\n // TODO: we should probably update this API to return the instances, but don't want to\n // break too much now\n return this.#trustedCertificates?.map((cert) => cert.toString('pem'))\n }\n\n /**\n * @deprecated use the global `getTrustedIssuersForVerification` instead\n */\n public get getTrustedCertificatesForVerification() {\n return this.#getTrustedCertificatesForVerification\n }\n\n /**\n * @deprecated use the global `getTrustedIssuersForVerification` instead\n */\n public setTrustedCertificatesForVerification(fn: X509ModuleConfigOptions['getTrustedCertificatesForVerification']) {\n this.#getTrustedCertificatesForVerification = fn\n }\n\n public get revocationCheck(): X509RevocationCheckOptionsWithDefaults {\n return withX509RevocationCheckDefaults(this.#revocationCheck)\n }\n\n public setRevocationCheck(options?: X509RevocationCheckOptions) {\n this.#revocationCheck = options\n }\n\n public setTrustedCertificates(trustedCertificates?: Array<string | X509Certificate>) {\n const certificateInstances = trustedCertificates?.map((trustedCertificate) =>\n typeof trustedCertificate === 'string'\n ? X509Certificate.fromEncodedCertificate(trustedCertificate)\n : trustedCertificate\n )\n this.#trustedCertificates = trustedCertificates?.length ? certificateInstances : undefined\n }\n\n public addTrustedCertificate(trustedCertificate: string | X509Certificate) {\n const certificateInstance =\n typeof trustedCertificate === 'string'\n ? X509Certificate.fromEncodedCertificate(trustedCertificate)\n : trustedCertificate\n\n if (!this.#trustedCertificates) {\n this.#trustedCertificates = []\n }\n\n this.#trustedCertificates.push(certificateInstance)\n }\n}\n"],"mappings":";;;;;;;;;AAwJA,IAAa,mBAAb,MAA8B;CAK5B,YAAmB,SAAmC;;;;EACpD,KAAK,uBAAuB,SAAS,mBAAmB;EACxD,IAAI,SAAS,uCACX,KAAK,sCAAsC,QAAQ,qCAAqC;EAE1F,IAAI,SAAS,iBACX,uBAAA,kBAAA,MAAwB,QAAQ,eAAA;CAEpC;CAEA,IAAW,sBAAsB;EAG/B,OAAA,uBAAA,sBAAO,IAAA,CAAA,EAA2B,KAAK,SAAS,KAAK,SAAS,KAAK,CAAC;CACtE;;;;CAKA,IAAW,wCAAwC;EACjD,OAAA,uBAAA,wCAAO,IAAA;CACT;;;;CAKA,sCAA6C,IAAsE;EACjH,uBAAA,wCAAA,MAA8C,EAAA;CAChD;CAEA,IAAW,kBAA0D;EACnE,OAAO,gCAAA,uBAAA,kBAAgC,IAAA,CAAqB;CAC9D;CAEA,mBAA0B,SAAsC;EAC9D,uBAAA,kBAAA,MAAwB,OAAA;CAC1B;CAEA,uBAA8B,qBAAuD;EACnF,MAAM,uBAAuB,qBAAqB,KAAK,uBACrD,OAAO,uBAAuB,WAC1B,gBAAgB,uBAAuB,kBAAkB,IACzD,kBACN;EACA,uBAAA,sBAAA,MAA4B,qBAAqB,SAAS,uBAAuB,KAAA,CAAA;CACnF;CAEA,sBAA6B,oBAA8C;EACzE,MAAM,sBACJ,OAAO,uBAAuB,WAC1B,gBAAgB,uBAAuB,kBAAkB,IACzD;EAEN,IAAI,CAAA,uBAAA,sBAAC,IAAA,GACH,uBAAA,sBAAA,MAA4B,CAAC,CAAA;EAG/B,uBAAA,sBAAA,IAAA,CAAA,CAA0B,KAAK,mBAAmB;CACpD;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"X509RevocationService.d.mts","names":[],"sources":["../../../src/modules/x509/X509RevocationService.ts"],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"X509RevocationService.d.mts","names":[],"sources":["../../../src/modules/x509/X509RevocationService.ts"],"mappings":";;;;;;;;iBA8BiB;EACf;EACA;EACA,QAAQ;EACR;EACA;;qBAaW;;;;SAIS,2BAClB,cAAc,gBACZ,aAAa,mBAAmB,0BAA0B,wCAC3D,QAAQ;;;;;;;;;;;;;SA2CS,gCAClB,cAAc,cACd,kBAAkB,mBAClB,QAAQ,kBACR,kBAAkB,OACjB,QAAQ;;;;;iBAkDU;;;;iBA2LN;;;;;iBAoBA;;;;iBAaA;;;;iBA0BM;;;;;;;iBAyDN;;;;;iBA2DM;;;;;;;;;;;;;;;;;;;iBAsEA;;;;;;;;;;iBAgDA;;;;;;;iBAkFN;;;;iBAaA;;;;;;;;;;;;SAsCK,+BAClB,cAAc,gBAEZ,KACA,mBACA,WACA,iBACA,oBACC,4CACF,QAAQ"}
|