@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
JavaScript
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