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

72 lines (71 loc) • 4.51 kB
import { convertLegacyTrustedCertificates } from "../x509/utils/convertLegacyTrustedCertificates.mjs"; import { X509Certificate } from "../x509/X509Certificate.mjs"; import { MdocError } from "./MdocError.mjs"; import { isMdocSupportedSignatureAlgorithm, mdocSupportedSignatureAlgorithms } from "./mdocSupportedAlgs.mjs"; import { DeviceNamespaces, DeviceSignedItems } from "@owf/mdoc"; //#region src/modules/mdoc/mdocUtil.ts /** * mdoc COSE structures require an explicit `alg`, but credo public JWKs generally don't carry one. */ function getMdocSignatureAlgForJwk(publicJwk) { const signatureAlgorithm = publicJwk.supportedSignatureAlgorithms.find(isMdocSupportedSignatureAlgorithm); if (!signatureAlgorithm) throw new MdocError(`No supported signature algorithm found for jwk ${publicJwk.jwkTypeHumanDescription}. Key supports algs ${publicJwk.supportedSignatureAlgorithms.join(", ")}. mdoc supports algs ${mdocSupportedSignatureAlgorithms.join(", ")}`); return signatureAlgorithm; } /** * The JSON representation of a public JWK, with `alg` filled in as the mdoc COSE structures require * it. The `kid` (needed to resolve the key for signing) is taken from the jwk as-is; it's up to the * caller to make sure the key id is set. */ function mdocSigningJwk(publicJwk) { const jwk = publicJwk.toJson(); return { ...jwk, alg: jwk.alg ?? getMdocSignatureAlgForJwk(publicJwk) }; } /** * Falls back to the `issuance` certs when no `status` certs are configured (`status: undefined`); an * explicit `status: []` is passed through. {@link assertMdocStatusListChainsMatchIssuanceChain} then * keeps the fallback from widening the trust set. */ function convertMdocTrustedCertificates(trustedCertificates) { return convertLegacyTrustedCertificates(trustedCertificates).map(({ issuance, status }) => ({ issuance, status: status ?? issuance, hasDedicatedStatusCertificates: status !== void 0 })); } /** * Maps the converted trusted certificates to the raw representation the `@owf/mdoc` library expects. */ function mdocTrustedCertificatesToRaw(trustedCertificates) { return trustedCertificates.map(({ issuance, status }) => ({ issuance: issuance.map((cert) => X509Certificate.fromEncodedCertificate(cert).rawCertificate), status: status.map((cert) => X509Certificate.fromEncodedCertificate(cert).rawCertificate) })); } /** * Without dedicated status certs, requires the status/identifier list chains to equal the issuance * chain, so the fallback can't accept a list signed by a different chain under the same trust anchor. */ function assertMdocStatusListChainsMatchIssuanceChain(trustedCertificates, chains) { const issuanceChain = chains.trustedIssuanceChain.map((cert) => X509Certificate.fromRawCertificate(cert)); const issuanceTrustAnchor = issuanceChain[issuanceChain.length - 1]; if (trustedCertificates.find(({ issuance }) => issuance.some((cert) => X509Certificate.fromEncodedCertificate(cert).equal(issuanceTrustAnchor)))?.hasDedicatedStatusCertificates) return; const chainMatchesIssuanceChain = (chain) => { const resolvedChain = chain.map((cert) => X509Certificate.fromRawCertificate(cert)); return resolvedChain.length === issuanceChain.length && resolvedChain.every((cert, i) => cert.equal(issuanceChain[i])); }; if (chains.trustedIdentifierListChain && !chainMatchesIssuanceChain(chains.trustedIdentifierListChain)) throw new MdocError("Trusted identifier list chain does not match the trusted issuance chain, and no trusted status certificates were provided for the trusted issuance certificate"); if (chains.trustedStatusListChain && !chainMatchesIssuanceChain(chains.trustedStatusListChain)) throw new MdocError("Trusted status list chain does not match the trusted issuance chain, and no trusted status certificates were provided for the trusted issuance certificate"); } function nameSpacesRecordToMap(nameSpaces) { return new Map(Object.entries(nameSpaces).map(([key, value]) => [key, new Map(Object.entries(value))])); } function nameSpacesRecordToDeviceNamespaces(nameSpaces) { return DeviceNamespaces.create({ deviceNamespaces: new Map(Array.from(nameSpacesRecordToMap(nameSpaces), ([nameSpace, items]) => [nameSpace, DeviceSignedItems.create({ deviceSignedItems: items })])) }); } //#endregion export { assertMdocStatusListChainsMatchIssuanceChain, convertMdocTrustedCertificates, getMdocSignatureAlgForJwk, mdocSigningJwk, mdocTrustedCertificatesToRaw, nameSpacesRecordToDeviceNamespaces, nameSpacesRecordToMap }; //# sourceMappingURL=mdocUtil.mjs.map