ISO mdoc / mDL (ISO 18013-5)
Verify the issuer-signed data of an ISO/IEC 18013-5 mdoc — the credential format behind mobile driving licences (mDL) and the ISO track of the EU Digital Identity Wallet. This is the relying-party side: confirm that the data elements a holder presents were signed by the issuer and have not been altered.
An mdoc's IssuerSigned structure carries the disclosed data elements (nameSpaces) and an issuerAuth that is a COSE_Sign1 (b.cose) over a Mobile Security Object (MSO). The MSO holds, per namespace, a SHA-256/384/512 digest of every issued element. b.mdoc.verifyIssuerSigned verifies the COSE signature with the issuer certificate carried in the COSE x5chain (label 33), parses the MSO, enforces its validityInfo window, and — the integrity check that makes selective disclosure trustworthy — recomputes the digest of every disclosed element (the full Tag-24 IssuerSignedItemBytes) and matches it against the MSO, constant-time. A disclosed element whose digest is absent or mismatched is refused.
Signing algorithms follow b.cose verification: the classical ES256 / 384 / 512 and EdDSA that real mDL issuers use are accepted (consume-what-exists; the caller names the allowlist). opts.trustAnchorsPem additionally verifies the issuer certificate chain and its validity at the asserted time.
Scope. Two halves are verified: issuer-data authentication (ISO 18013-5 §9.1.2.4 — the data is genuine and issuer-signed, via verifyIssuerSigned) and mdoc device authentication (§9.1.3 — holder binding over the verifier's SessionTranscript, via verifyDeviceAuth). Device auth covers the COSE_Sign1 signature variant; the COSE_Mac0 (deviceMac) variant is refused rather than mis-verified. Composes b.cose + b.cbor; no new runtime dependency. Distinct from W3C VCDM (b.vc) and IETF SD-JWT VC (b.auth.sdJwtVc) — the three credential ecosystems.
b.mdoc.verifyIssuerSigned(issuerSigned, opts) #
{
{
algorithms: string[], // required — accepted COSE alg names (ES256/384/512, EdDSA)
trustAnchorsPem: string|string[], // optional issuer roots — enables chain + validity verification
expectedDocType: string, // require the MSO docType to match (e.g. "org.iso.18013.5.1.mDL")
at: Date, // validity instant (default now); must be a valid Date
maxBytes: number, // forwarded to b.cbor.decode
maxDepth: number,
}
}
Verify the issuer-signed data of an ISO 18013-5 mdoc and return the disclosed elements. issuerSigned is the CBOR IssuerSigned map (the operator extracts it from the device response / QR). The COSE_Sign1 issuerAuth is verified with the issuer certificate from its x5chain header against the mandatory opts.algorithms allowlist; the MSO validityInfo window is enforced; and every disclosed element's digest is matched against the Mobile Security Object (a mismatch or absence is refused). Pass opts.trustAnchorsPem to also verify the issuer certificate chain.
var out = await b.mdoc.verifyIssuerSigned(issuerSignedBytes, {
algorithms: ["ES256"], expectedDocType: "org.iso.18013.5.1.mDL",
});
// → { docType, validityInfo, namespaces: { "org.iso.18013.5.1": { family_name, age_over_18, … } }, signerCert, alg }
b.mdoc.verifyDeviceAuth(opts) #
{
{
deviceKey: object, // COSE_Key (from verifyIssuerSigned().deviceKey) or a KeyObject / PEM
deviceSigned: object, // the DeviceSigned structure (CBOR bytes or decoded)
docType: string, // the document type (must match the issuer-signed docType)
sessionTranscript: any, // the SessionTranscript (CBOR bytes or decoded) bound by the protocol
algorithms: string[], // required — accepted COSE alg names (ES256/384/512, EdDSA)
maxBytes: number, // forwarded to b.cbor.decode
maxDepth: number,
}
}
Verify the device-authentication half of an ISO 18013-5 mdoc (§9.1.3, signature variant) — the proof that the holder controls the device key the issuer bound into the MSO, which stops a captured issuer-signed document from being replayed by anyone else. The device's COSE_Sign1 (deviceSigned.deviceAuth.deviceSignature) is verified over the detached DeviceAuthentication structure (["DeviceAuthentication", SessionTranscript, DocType, DeviceNameSpacesBytes]) with the device key from the issuer-signed MSO (verifyIssuerSigned(...).deviceKey). The sessionTranscript binds the proof to this exact exchange and is supplied by the operator (the presentation protocol — e.g. OpenID4VP — defines it). The MAC variant (deviceMac / COSE_Mac0, used in proximity flows with a reader ephemeral key) is not yet supported and is refused with mdoc/device-mac-unsupported.
var issuer = await b.mdoc.verifyIssuerSigned(issuerSignedBytes, { algorithms: ["ES256"] });
var dev = await b.mdoc.verifyDeviceAuth({ deviceKey: issuer.deviceKey, deviceSigned: deviceSignedBytes, docType: issuer.docType, sessionTranscript: transcript, algorithms: ["ES256"] });
// → { docType, alg, deviceNamespaces }
Last updated 2026-08-08T16:39:49.652Z by seeder.