UNPKG

@credo-ts/core

Version:

<p align="center"> <br /> <img alt="Credo Logo" src="https://github.com/openwallet-foundation/credo-ts/blob/c7886cb8377ceb8ee4efe8d264211e561a75072d/images/credo-logo.png" height="250px" /> </p> <h1 align="center"><b>Credo - Core</b></h1

96 lines (92 loc) • 6.19 kB
import { CredoError } from "../../error/CredoError.mjs"; import "../../error/index.mjs"; import { asArray } from "../../utils/array.mjs"; import { isDid } from "../../utils/did.mjs"; import "../../utils/index.mjs"; import "../../agent/index.mjs"; import { PublicJwk } from "../kms/jwk/PublicJwk.mjs"; import "../kms/index.mjs"; import { parseDid } from "../dids/domain/parse.mjs"; import { getPublicJwkFromVerificationMethod, getSupportedVerificationMethodTypesForPublicJwk } from "../dids/domain/key-type/keyDidMapping.mjs"; import { DidResolverService } from "../dids/services/DidResolverService.mjs"; import { DidsApi } from "../dids/DidsApi.mjs"; import "../dids/index.mjs"; import { W3cV2JwtVerifiableCredential } from "./jwt-vc/W3cV2JwtVerifiableCredential.mjs"; import { W3cV2SdJwtVerifiableCredential } from "./sd-jwt-vc/W3cV2SdJwtVerifiableCredential.mjs"; import { extractKeyFromHolderBinding, parseHolderBindingFromCredential } from "../sd-jwt-vc/utils.mjs"; import "./sd-jwt-vc/index.mjs"; import { W3cV2JwtVerifiablePresentation } from "./jwt-vc/W3cV2JwtVerifiablePresentation.mjs"; import "./jwt-vc/index.mjs"; import "./models/index.mjs"; //#region src/modules/vc/v2-jwt-utils.ts async function validateAndResolveVerificationMethod(agentContext, verificationMethod, allowsPurposes) { if (!isDid(verificationMethod)) throw new CredoError("Only did identifiers are supported as verification method"); const parsedDid = parseDid(verificationMethod); if (!parsedDid.fragment) throw new CredoError(`didUrl '${parsedDid.didUrl}' does not contain a '#'. Unable to derive key from did document`); const { didDocument, keys } = await agentContext.resolve(DidsApi).resolveCreatedDidDocumentWithKeys(parsedDid.did); const verificationMethodObject = didDocument.dereferenceKey(verificationMethod, allowsPurposes); const publicJwk = getPublicJwkFromVerificationMethod(verificationMethodObject); publicJwk.keyId = keys?.find(({ didDocumentRelativeKeyId }) => verificationMethodObject.id.endsWith(didDocumentRelativeKeyId))?.kmsKeyId ?? publicJwk.legacyKeyId; return publicJwk; } async function extractHolderFromPresentationCredentials(agentContext, presentation) { const credentials = asArray(presentation.verifiableCredential); if (credentials.length !== 1) throw new CredoError("Only a single verifiable credential is supported in a presentation"); const credential = credentials[0]; let claims; if (credential.envelopedCredential instanceof W3cV2SdJwtVerifiableCredential) claims = credential.envelopedCredential.sdJwt.prettyClaims; else claims = credential.envelopedCredential.jwt.payload.toJson(); const holderBinding = parseHolderBindingFromCredential(claims); if (!holderBinding) throw new CredoError("No holder binding found in credential included in presentation"); return await extractKeyFromHolderBinding(agentContext, holderBinding, { forSigning: true }); } /** * This method tries to find the verification method associated with the JWT credential or presentation. * This verification method can then be used to verify the credential or presentation signature. */ async function getVerificationMethodForJwt(agentContext, credential, purpose) { let alg; let kid; let iss; if (credential instanceof W3cV2JwtVerifiableCredential) { alg = credential.jwt.header.alg; kid = credential.jwt.header.kid; iss = credential.jwt.payload.iss ?? credential.resolvedCredential.issuerId; } else if (credential instanceof W3cV2JwtVerifiablePresentation) { alg = credential.jwt.header.alg; kid = credential.jwt.header.kid; iss = credential.jwt.payload.iss ?? credential.resolvedPresentation.holderId; } else if (credential instanceof W3cV2SdJwtVerifiableCredential) { alg = credential.sdJwt.header.alg; kid = credential.sdJwt.header.kid; iss = credential.sdJwt.payload.iss ?? credential.resolvedCredential.issuerId; } else { alg = credential.sdJwt.header.alg; kid = credential.sdJwt.header.kid; iss = credential.sdJwt.payload.iss ?? credential.resolvedPresentation.holderId; } const didResolver = agentContext.dependencyManager.resolve(DidResolverService); let verificationMethod; if (kid?.startsWith("#")) { if (!iss || !isDid(iss)) throw new CredoError(`JWT 'iss' MUST be a did when 'kid' is a relative did url`); verificationMethod = (await didResolver.resolveDidDocument(agentContext, iss)).dereferenceKey(`${iss}${kid}`, purpose); } else if (kid && isDid(kid)) { const didDocument = await didResolver.resolveDidDocument(agentContext, kid); verificationMethod = didDocument.dereferenceKey(kid, purpose); if (iss && didDocument.id !== iss) throw new CredoError(`kid '${kid}' does not match id of signer (holder/issuer) '${iss}'`); } else { if (!iss) throw new CredoError(`JWT 'iss' MUST be present in payload when no 'kid' is specified`); const jwkClass = PublicJwk.supportedPublicJwkClassForSignatureAlgorithm(alg); const supportedVerificationMethodTypes = getSupportedVerificationMethodTypesForPublicJwk(jwkClass); const didDocument = await didResolver.resolveDidDocument(agentContext, iss); const verificationMethods = didDocument.assertionMethod?.map((v) => typeof v === "string" ? didDocument.dereferenceVerificationMethod(v) : v).filter((v) => supportedVerificationMethodTypes.includes(v.type)) ?? []; 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.`); 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.`); verificationMethod = verificationMethods[0]; } if (iss && verificationMethod.controller !== iss) throw new CredoError(`Verification method controller '${verificationMethod.controller}' does not match the signer '${iss}'`); return verificationMethod; } //#endregion export { extractHolderFromPresentationCredentials, getVerificationMethodForJwt, validateAndResolveVerificationMethod }; //# sourceMappingURL=v2-jwt-utils.mjs.map