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

175 lines (174 loc) • 8.01 kB
import _classPrivateFieldInitSpec from "../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/classPrivateFieldInitSpec.mjs"; import _classPrivateFieldGet2 from "../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/classPrivateFieldGet2.mjs"; import _classPrivateFieldSet2 from "../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/classPrivateFieldSet2.mjs"; import { isKnownJwaSignatureAlgorithm } from "../kms/jwk/jwa.mjs"; import { PublicJwk } from "../kms/jwk/PublicJwk.mjs"; import "../kms/index.mjs"; import { X509Certificate } from "../x509/X509Certificate.mjs"; import { X509ModuleConfig } from "../x509/X509ModuleConfig.mjs"; import { TrustedIssuerContext } from "../../agent/TrustedIssuerContext.mjs"; import "../vc/models/ClaimFormat.mjs"; import "../vc/index.mjs"; import { getMdocContext } from "../../crypto/contexts/mdocContext.mjs"; import "../x509/index.mjs"; import { MdocError } from "./MdocError.mjs"; import { isMdocSupportedSignatureAlgorithm, mdocSupportedSignatureAlgorithms } from "./mdocSupportedAlgs.mjs"; import { assertMdocStatusListChainsMatchIssuanceChain, convertMdocTrustedCertificates, mdocTrustedCertificatesToRaw } from "./mdocUtil.mjs"; import { DeviceKey, DeviceKeyInfo, Holder, Issuer, IssuerSigned, KeyAuthorizations, SignatureAlgorithm } from "@owf/mdoc"; //#region src/modules/mdoc/Mdoc.ts var _deviceKeyId = /* @__PURE__ */ new WeakMap(); /** * This class represents a IssuerSigned Mdoc Document, * which are the actual credentials being issued to holders. */ var Mdoc = class Mdoc { get base64Url() { return this.issuerSigned.encodedForOid4Vci; } constructor(issuerSigned) { this.issuerSigned = issuerSigned; _classPrivateFieldInitSpec(this, _deviceKeyId, void 0); } /** * claim format is convenience method added to all credential instances */ get claimFormat() { return "mso_mdoc"; } /** * Encoded is convenience method added to all credential instances */ get encoded() { return this.issuerSigned.encodedForOid4Vci; } /** * Get the device key to which the mdoc is bound */ get deviceKey() { const publicJwk = PublicJwk.fromUnknown(this.issuerSigned.issuerAuth.mobileSecurityObject.deviceKeyInfo.deviceKey.jwk); if (_classPrivateFieldGet2(_deviceKeyId, this)) publicJwk.keyId = _classPrivateFieldGet2(_deviceKeyId, this); return publicJwk; } set deviceKeyId(keyId) { _classPrivateFieldSet2(_deviceKeyId, this, keyId); } get deviceKeyId() { const deviceKey = this.deviceKey; if (deviceKey.hasKeyId) return deviceKey.keyId; } static fromBase64Url(mdocBase64Url) { const issuerSigned = IssuerSigned.fromEncodedForOid4Vci(mdocBase64Url); return new Mdoc(issuerSigned); } get docType() { return this.issuerSigned.issuerAuth.mobileSecurityObject.docType; } get alg() { const jwaAlg = this.issuerSigned.issuerAuth.jwaAlgorithm; if (!jwaAlg) throw new MdocError("The IssuerAuth does not have a valid signature algorithm in the header"); if (isKnownJwaSignatureAlgorithm(jwaAlg)) return jwaAlg; throw new MdocError(`Cannot parse mdoc. The signature algorithm '${jwaAlg}' is not supported.`); } get validityInfo() { const { signed, validFrom, validUntil } = this.issuerSigned.issuerAuth.mobileSecurityObject.validityInfo; return { signed, validFrom, validUntil }; } get issuerSignedCertificateChain() { return this.issuerSigned.issuerAuth.certificateChain; } get signingCertificate() { return this.issuerSigned.issuerAuth.certificate; } get issuerSignedNamespaces() { if (!this.issuerSigned.issuerNamespaces?.issuerNamespaces) return {}; return Object.fromEntries(Array.from(this.issuerSigned.issuerNamespaces.issuerNamespaces.entries()).map(([namespace, value]) => [namespace, Object.fromEntries(Array.from(value.values()).map((v) => [v.elementIdentifier, v.elementValue]))])); } static async sign(agentContext, options) { const { docType, validityInfo, namespaces, holderKey, issuerCertificate, keyAuthorizations } = options; const mdocContext = getMdocContext(agentContext); const issuer = new Issuer(docType, mdocContext); for (const [namespace, namespaceRecord] of Object.entries(namespaces)) issuer.addIssuerNamespace(namespace, namespaceRecord); const issuerKey = Array.isArray(issuerCertificate) ? issuerCertificate[0].publicJwk : issuerCertificate.publicJwk; const alg = issuerKey.supportedSignatureAlgorithms.find(isMdocSupportedSignatureAlgorithm); if (!alg) throw new MdocError(`Unable to create sign mdoc. No supported signature algorithm found to sign mdoc for jwk with key ${issuerKey.jwkTypeHumanDescription}. Key supports algs ${issuerKey.supportedSignatureAlgorithms.join(", ")}. mdoc supports algs ${mdocSupportedSignatureAlgorithms.join(", ")}`); const now = /* @__PURE__ */ new Date(); const issuerSigned = await issuer.sign({ digestAlgorithm: "SHA-256", validityInfo: { ...validityInfo, signed: validityInfo.signed ?? now, validFrom: validityInfo.validFrom ?? now }, algorithm: SignatureAlgorithm[alg], certificates: Array.isArray(issuerCertificate) ? issuerCertificate.map((c) => c.rawCertificate) : [issuerCertificate.rawCertificate], deviceKeyInfo: DeviceKeyInfo.create({ deviceKey: DeviceKey.fromJwk(holderKey.toJson()), keyAuthorizations: keyAuthorizations ? KeyAuthorizations.create({ namespaces: keyAuthorizations.namespaces, dataElements: keyAuthorizations.dataElements ? new Map(Object.entries(keyAuthorizations.dataElements)) : void 0 }) : void 0 }), signingKey: issuerKey.toJson(), status: options.statusInfo ? { statusList: { idx: options.statusInfo.index, uri: options.statusInfo.uri, certificate: options.statusInfo.certificate?.rawCertificate } } : void 0 }); return new Mdoc(issuerSigned); } async verify(agentContext, options) { const x509ModuleConfig = agentContext.dependencyManager.resolve(X509ModuleConfig); const certificateChain = this.issuerSigned.issuerAuth.certificateChain.map((certificate) => X509Certificate.fromRawCertificate(certificate)); let trustedCertificates = options?.trustedCertificates; if (!trustedCertificates) trustedCertificates = (await TrustedIssuerContext.getTrustedIssuersForVerification(agentContext, { verification: { type: "credential", credential: this }, signer: { certificateChain, method: "x509" } }))?.trustedIssuers ?? await x509ModuleConfig.getTrustedCertificatesForVerification?.(agentContext, { verification: { type: "credential", credential: this }, certificateChain }) ?? x509ModuleConfig.trustedCertificates; if (!trustedCertificates) throw new MdocError("No trusted certificates found. Cannot verify mdoc."); const mdocContext = getMdocContext(agentContext, { now: options?.now }); try { const convertedTrustedCertificates = convertMdocTrustedCertificates(trustedCertificates); const { trustedIssuanceChain, trustedStatusListChain, trustedIdentifierListChain } = await Holder.verifyIssuerSigned({ trustedCertificates: mdocTrustedCertificatesToRaw(convertedTrustedCertificates), issuerSigned: this.issuerSigned, disableCertificateChainValidation: false, disableStatusValidation: false, now: options?.now }, mdocContext); if (!trustedIssuanceChain) throw new MdocError("Unable to determine a trusted issuance chain"); const issuanceChain = trustedIssuanceChain.map((c) => X509Certificate.fromRawCertificate(c)); if (!(certificateChain.length <= issuanceChain.length && certificateChain.every((cert, i) => cert.equal(issuanceChain[i])))) throw new MdocError("Certificate chain does not match the trusted issuance chain"); assertMdocStatusListChainsMatchIssuanceChain(convertedTrustedCertificates, { trustedIssuanceChain, trustedStatusListChain, trustedIdentifierListChain }); return { isValid: true }; } catch (error) { return { isValid: false, error: error.message }; } } }; //#endregion export { Mdoc }; //# sourceMappingURL=Mdoc.mjs.map