@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
1 lines • 9.78 kB
Source Map (JSON)
{"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, W3cV2JwtVerifiablePresentation } from './jwt-vc'\nimport { W3cV2Presentation } from './models'\nimport { W3cV2SdJwtVerifiableCredential, W3cV2SdJwtVerifiablePresentation } from './sd-jwt-vc'\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 // At the moment, we only support signing presentations with a single credential\n // Technically, it should be possible to support more than a single one. However,\n // in the context we support (OID4VP) it doesn't make sense to support multiple ones.\n const credentials = asArray(presentation.verifiableCredential)\n if (credentials.length !== 1) {\n throw new CredoError('Only a single verifiable credential is supported in a presentation')\n }\n\n const credential = credentials[0]\n let claims: Record<string, unknown>\n\n if (credential.envelopedCredential instanceof W3cV2SdJwtVerifiableCredential) {\n claims = credential.envelopedCredential.sdJwt.prettyClaims\n } else {\n claims = credential.envelopedCredential.jwt.payload.toJson()\n }\n\n // We require the credential to include a holder binding in the form of a 'cnf' claim\n const holderBinding = parseHolderBindingFromCredential(claims)\n if (!holderBinding) {\n throw new CredoError('No holder binding found in credential included in presentation')\n }\n\n return await extractKeyFromHolderBinding(agentContext, holderBinding, { forSigning: true })\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 =\n didDocument.assertionMethod\n ?.map((v) => (typeof v === 'string' ? didDocument.dereferenceVerificationMethod(v) : v))\n .filter((v) => supportedVerificationMethodTypes.includes(v.type)) ?? []\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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"}