@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 • 7.08 kB
Source Map (JSON)
{"version":3,"file":"utils.mjs","names":[],"sources":["../../../src/modules/sd-jwt-vc/utils.ts"],"sourcesContent":["import type { Signer, Verifier } from '@sd-jwt/types'\nimport { AgentContext } from '../../agent'\nimport { CredoError } from '../../error'\nimport { TypedArrayEncoder } from '../../utils'\nimport { DidResolverService, DidsApi, getPublicJwkFromVerificationMethod, parseDid } from '../dids'\nimport { type Jwk, KeyManagementApi, PublicJwk } from '../kms'\nimport type { SdJwtVcHolderBinding } from './SdJwtVcOptions'\n\nexport async function resolveSigningPublicJwkFromDidUrl(agentContext: AgentContext, didUrl: string) {\n const dids = agentContext.dependencyManager.resolve(DidsApi)\n\n const { publicJwk } = await dids.resolveVerificationMethodFromCreatedDidRecord(didUrl)\n return publicJwk\n}\n\nexport async function resolveDidUrl(agentContext: AgentContext, didUrl: string) {\n const didResolver = agentContext.dependencyManager.resolve(DidResolverService)\n const didDocument = await didResolver.resolveDidDocument(agentContext, didUrl)\n\n return {\n verificationMethod: didDocument.dereferenceKey(didUrl, ['assertionMethod']),\n didDocument,\n }\n}\n\nexport async function extractKeyFromHolderBinding(\n agentContext: AgentContext,\n holder: SdJwtVcHolderBinding,\n { forSigning = false, jwkKeyId }: { forSigning?: boolean; jwkKeyId?: string } = {}\n) {\n if (holder.method === 'did') {\n const parsedDid = parseDid(holder.didUrl)\n if (!parsedDid.fragment) {\n throw new CredoError(`didUrl '${holder.didUrl}' does not contain a '#'. Unable to derive key from did document`)\n }\n\n let publicJwk: PublicJwk\n if (forSigning) {\n publicJwk = await resolveSigningPublicJwkFromDidUrl(agentContext, holder.didUrl)\n } else {\n const { verificationMethod } = await resolveDidUrl(agentContext, holder.didUrl)\n publicJwk = getPublicJwkFromVerificationMethod(verificationMethod)\n }\n\n const supportedSignatureAlgorithms = publicJwk.supportedSignatureAlgorithms\n if (supportedSignatureAlgorithms.length === 0) {\n throw new CredoError(`No supported JWA signature algorithms found for key ${publicJwk.jwkTypeHumanDescription}`)\n }\n const alg = supportedSignatureAlgorithms[0]\n\n return {\n alg,\n publicJwk,\n cnf: {\n // We need to include the whole didUrl here, otherwise the verifier\n // won't know which did it is associated with\n kid: holder.didUrl,\n },\n }\n }\n if (holder.method === 'jwk') {\n const publicJwk = holder.jwk\n const alg = publicJwk.supportedSignatureAlgorithms[0]\n\n // FIXME: shouldn't we use `if (forSigning && !publicJwk.keyId)`, or at least use keyId over legacyKeyId\n // It depends on whether we foresee security issues with trusting the `kid` field in the issued credential jwk.\n // If there is no key id configured when signing, we assume this credential was issued before we included key ids\n // and the we use the legacy key id.\n if (forSigning) {\n publicJwk.keyId = jwkKeyId ?? publicJwk.legacyKeyId\n }\n\n return {\n alg,\n publicJwk,\n cnf: {\n jwk: publicJwk.toJson(),\n },\n }\n }\n\n throw new CredoError(\"Unsupported credential holder binding. Only 'did' and 'jwk' are supported at the moment.\")\n}\n\n/**\n * @todo validate the JWT header (alg)\n */\nexport function getSdJwtSigner(agentContext: AgentContext, key: PublicJwk): Signer {\n const kms = agentContext.resolve(KeyManagementApi)\n\n return async (input: string) => {\n const result = await kms.sign({\n keyId: key.keyId,\n data: TypedArrayEncoder.fromUtf8String(input),\n algorithm: key.signatureAlgorithm,\n })\n\n return TypedArrayEncoder.toBase64Url(result.signature)\n }\n}\n\n/**\n * @todo validate the JWT header (alg)\n */\nexport function getSdJwtVerifier(agentContext: AgentContext, key: PublicJwk): Verifier {\n const kms = agentContext.resolve(KeyManagementApi)\n\n return async (message: string, signatureBase64Url: string) => {\n const result = await kms.verify({\n signature: TypedArrayEncoder.fromBase64Url(signatureBase64Url),\n key: {\n publicJwk: key.toJson(),\n },\n data: TypedArrayEncoder.fromUtf8String(message),\n algorithm: key.signatureAlgorithm,\n })\n\n return result.verified\n }\n}\n\nexport interface CnfPayload {\n jwk?: Jwk\n kid?: string\n}\n\nexport function parseHolderBindingFromCredential(payload?: Record<string, unknown>): SdJwtVcHolderBinding | null {\n if (!payload) {\n throw new CredoError('Unable to extract payload from SD-JWT VC')\n }\n\n if (!payload.cnf) {\n return null\n }\n const cnf: CnfPayload = payload.cnf\n\n if (cnf.jwk) {\n return {\n method: 'jwk',\n jwk: PublicJwk.fromUnknown(cnf.jwk),\n }\n }\n if (cnf.kid) {\n if (!cnf.kid.startsWith('did:') || !cnf.kid.includes('#')) {\n throw new CredoError('Invalid holder kid for did. Only absolute KIDs for cnf are supported')\n }\n return {\n method: 'did',\n didUrl: cnf.kid,\n }\n }\n\n throw new CredoError(\"Unsupported credential holder binding. Only 'did' and 'jwk' are supported at the moment.\")\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAQA,eAAsB,kCAAkC,cAA4B,QAAgB;CAGlG,MAAM,EAAE,cAAc,MAFT,aAAa,kBAAkB,QAAQ,QAAQ,CAE3B,8CAA8C,OAAO;AACtF,QAAO;;AAGT,eAAsB,cAAc,cAA4B,QAAgB;CAE9E,MAAM,cAAc,MADA,aAAa,kBAAkB,QAAQ,mBAAmB,CACxC,mBAAmB,cAAc,OAAO;AAE9E,QAAO;EACL,oBAAoB,YAAY,eAAe,QAAQ,CAAC,kBAAkB,CAAC;EAC3E;EACD;;AAGH,eAAsB,4BACpB,cACA,QACA,EAAE,aAAa,OAAO,aAA0D,EAAE,EAClF;AACA,KAAI,OAAO,WAAW,OAAO;AAE3B,MAAI,CADc,SAAS,OAAO,OAAO,CAC1B,SACb,OAAM,IAAI,WAAW,WAAW,OAAO,OAAO,kEAAkE;EAGlH,IAAI;AACJ,MAAI,WACF,aAAY,MAAM,kCAAkC,cAAc,OAAO,OAAO;OAC3E;GACL,MAAM,EAAE,uBAAuB,MAAM,cAAc,cAAc,OAAO,OAAO;AAC/E,eAAY,mCAAmC,mBAAmB;;EAGpE,MAAM,+BAA+B,UAAU;AAC/C,MAAI,6BAA6B,WAAW,EAC1C,OAAM,IAAI,WAAW,uDAAuD,UAAU,0BAA0B;AAIlH,SAAO;GACL,KAHU,6BAA6B;GAIvC;GACA,KAAK,EAGH,KAAK,OAAO,QACb;GACF;;AAEH,KAAI,OAAO,WAAW,OAAO;EAC3B,MAAM,YAAY,OAAO;EACzB,MAAM,MAAM,UAAU,6BAA6B;AAMnD,MAAI,WACF,WAAU,QAAQ,YAAY,UAAU;AAG1C,SAAO;GACL;GACA;GACA,KAAK,EACH,KAAK,UAAU,QAAQ,EACxB;GACF;;AAGH,OAAM,IAAI,WAAW,2FAA2F;;;;;AAMlH,SAAgB,eAAe,cAA4B,KAAwB;CACjF,MAAM,MAAM,aAAa,QAAQ,iBAAiB;AAElD,QAAO,OAAO,UAAkB;EAC9B,MAAM,SAAS,MAAM,IAAI,KAAK;GAC5B,OAAO,IAAI;GACX,MAAM,kBAAkB,eAAe,MAAM;GAC7C,WAAW,IAAI;GAChB,CAAC;AAEF,SAAO,kBAAkB,YAAY,OAAO,UAAU;;;;;;AAO1D,SAAgB,iBAAiB,cAA4B,KAA0B;CACrF,MAAM,MAAM,aAAa,QAAQ,iBAAiB;AAElD,QAAO,OAAO,SAAiB,uBAA+B;AAU5D,UATe,MAAM,IAAI,OAAO;GAC9B,WAAW,kBAAkB,cAAc,mBAAmB;GAC9D,KAAK,EACH,WAAW,IAAI,QAAQ,EACxB;GACD,MAAM,kBAAkB,eAAe,QAAQ;GAC/C,WAAW,IAAI;GAChB,CAAC,EAEY;;;AASlB,SAAgB,iCAAiC,SAAgE;AAC/G,KAAI,CAAC,QACH,OAAM,IAAI,WAAW,2CAA2C;AAGlE,KAAI,CAAC,QAAQ,IACX,QAAO;CAET,MAAM,MAAkB,QAAQ;AAEhC,KAAI,IAAI,IACN,QAAO;EACL,QAAQ;EACR,KAAK,UAAU,YAAY,IAAI,IAAI;EACpC;AAEH,KAAI,IAAI,KAAK;AACX,MAAI,CAAC,IAAI,IAAI,WAAW,OAAO,IAAI,CAAC,IAAI,IAAI,SAAS,IAAI,CACvD,OAAM,IAAI,WAAW,uEAAuE;AAE9F,SAAO;GACL,QAAQ;GACR,QAAQ,IAAI;GACb;;AAGH,OAAM,IAAI,WAAW,2FAA2F"}