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