Wallet programmes have two mainstream credential formats to choose from, ISO mdoc and SD-JWT VC, and picking the wrong one, or supporting only one, decides which relying parties can verify your credential and in which settings. The ISO/IEC 18013-5 mdoc is a CBOR and COSE structure built for the mobile driving licence and for in-person checks. SD-JWT VC is a JSON and JOSE structure from the IETF built for online flows. Both use salted hashes for selective disclosure, both can bind a credential to a device key, and the EU Digital Identity Wallet requires wallets to support both. This guide compares them on encoding and signatures, proximity versus online presentation, device binding, unlinkability, the EUDI Architecture and Reference Framework (ARF) rules, and the work each imposes on relying parties. It is for wallet architects, issuers, relying party teams and assessors; SD-JWT mechanics are in the SD-JWT and SD-JWT VC Guide, not repeated here. Standards status was checked on 14 November 2026.
Key takeaways
- The short answer is usually "both". The ARF requires PID Providers to issue every PID in both formats (PID_02) and Wallet Units to support both, so the real decision is which format a relying party verifies first and which an attestation rulebook mandates.
- Offline, in-person checks need mdoc. ISO/IEC 18013-5 defines NFC, QR, BLE and Wi-Fi Aware proximity flows. The ARF states that SD-JWT VC attestations cannot be used in proximity presentations, because OpenID4VP needs internet connectivity.
- Device binding is built into mdoc and optional in SD-JWT VC. mdoc authentication is mandatory in 18013-5. Key binding is optional in SD-JWT VC, so verifiers must demand it with
require_cryptographic_holder_bindingand reject anything else. - Neither format is unlinkable by itself. Both carry fixed digests, salts, keys and signatures that colluding verifiers can correlate. Single-use batch issuance fixes verifier linkability; only zero-knowledge proofs address issuer linkability, and none is selected yet in the ARF.
- Relying party effort differs by stack, not by security. JSON web teams find SD-JWT VC familiar; mdoc needs CBOR, COSE and SessionTranscript handling. Pin HAIP 1.0 and OpenID4VP 1.0.
What each format is
ISO mdoc is the data structure defined in ISO/IEC 18013-5:2021, "Mobile driving licence (mDL) application". ISO lists the first edition as published in September 2021 and marks it "to be revised", with a next edition at Draft International Standard stage. Only the mDL attribute set is driving-licence specific; the ARF notes that the rest is generic, so any attestation type can be defined as a CBOR scheme under its own docType and namespaces. ISO/IEC 23220-2 generalises the attribute encoding, and ISO/IEC 23220-4, a general presentation standard, is still in preparation. ISO/IEC TS 18013-7:2025 adds remote presentation.
SD-JWT VC is "SD-JWT-based Verifiable Digital Credentials", an IETF OAuth working group Internet-Draft. On 14 November 2026 the current version was draft-ietf-oauth-sd-jwt-vc-26 (6 November 2026), in IESG Evaluation with the intended status of Proposed Standard. It layers a credential type (vct), issuer key discovery, type metadata and status on top of RFC 9901 SD-JWT. Because the draft still moves, ecosystems pin a profile: the OpenID4VC High Assurance Interoperability Profile (HAIP) 1.0, a Final specification published 24 December 2025, defines the "IETF SD-JWT VC Profile" in Section 6.1 that ARF Topic 12 rulebooks must follow.
The optional third format, W3C VCDM 2.0, is limited to non-qualified attestations in the EUDI Wallet; see the Verifiable Credentials Guide.
Side-by-side comparison
| Dimension | ISO mdoc (18013-5) | SD-JWT VC |
|---|---|---|
| Standard body and status | ISO/IEC 18013-5:2021 (published), TS 18013-7:2025 for remote | IETF Internet-Draft (draft-26, IESG Evaluation); RFC 9901 underneath is final |
| Encoding | CBOR (RFC 8949), binary | JSON in a compact JWT string |
| Signature container | COSE_Sign1 (issuerAuth) over the Mobile Security Object | JWS over the issuer-signed JWT |
| Selective disclosure | Salted digest per data element in valueDigests | Salted digest per claim in _sd arrays, disclosures sent in clear |
| Type identifier | docType, for example org.iso.18013.5.1.mDL; attributes in namespaces such as eu.europa.ec.eudi.pid.1 | vct, for example urn:eudi:pid:1; claim names from the IANA JWT registry, public or private names |
| Issuer trust | X.509 chain in COSE x5chain to an issuing authority root | HAIP: X.509 x5c mandatory, signing certificate not self-signed |
| Device binding | Mandatory (mdoc authentication with deviceKey) | Optional in the draft (cnf plus KB-JWT); mandatory when requested |
| Proximity presentation | Yes: QR or NFC engagement, BLE, NFC or Wi-Fi Aware transfer | Not in the EUDI ecosystem (OpenID4VP requires internet) |
| Remote presentation | ISO/IEC TS 18013-7 or OpenID4VP (mso_mdoc) | OpenID4VP (dc+sd-jwt) |
| Status and revocation | MSO status; HAIP requires the mechanism from the 18013-5 second edition | status.status_list per Token Status List |
Encoding and signature models
The ARF calls the two salted-hash mechanisms "conceptually identical"; the difference is where hashes and clear values live.
mdoc: the Mobile Security Object
An issuer builds one IssuerSignedItem per data element, a CBOR map of digestID, random (the salt), elementIdentifier and elementValue. It hashes each item and places the digests in the Mobile Security Object (MSO) under valueDigests, grouped by namespace. The MSO also carries version, digestAlgorithm, docType, deviceKeyInfo (the holder's public deviceKey and optional key authorisations) and validityInfo (signed, validFrom, validUntil, optional expectedUpdate). The issuer signs the MSO in a COSE_Sign1 structure called issuerAuth, with the document signer certificate chain in the x5chain header. To disclose an element, the wallet returns the matching IssuerSignedItem; the verifier hashes it and looks for the digest in the signed MSO.
SD-JWT VC: digests inside a JWT
The issuer creates a disclosure per claim (salt, name, value), places its digest in an _sd array in the JWT payload and signs the JWT. The holder appends only the chosen disclosures after tildes. HAIP requires compact serialisation, ES256 (ECDSA P-256 with SHA-256) for issuers, wallets and verifiers, and SHA-256 support for digests in both formats (HAIP Sections 6.1, 7 and 8).
Practical consequence: mdoc elements are typed CBOR values, compact over NFC and BLE. SD-JWT VC is text any JOSE stack parses and developers can read during triage.
Proximity versus online presentation
- Proximity (mdoc only): 18013-5 defines device engagement by QR code or NFC, then data transfer over BLE, NFC or Wi-Fi Aware, with session encryption and reader authentication. It works with no internet on either side. ARF Topic 12 requires a rulebook to specify the mdoc format when an attestation must be presentable in proximity without internet, and explains that the only protocol for SD-JWT VC, OpenID4VP, cannot work offline. Proximity support is optional for relying parties (ProxId_01a) but mandatory for Wallet Units (OIA_01).
- Remote (both): the ARF lists OpenID4VP over redirects and custom URI schemes, OpenID4VP over the W3C Digital Credentials API, ISO/IEC 18013-7 over the Digital Credentials API, and optionally 18013-7 over custom URI schemes. OpenID4VP carries both formats, identified as
mso_mdocanddc+sd-jwt(OpenID4VP Appendix B). See the W3C Digital Credentials API Guide and the OpenID for Verifiable Presentations (OpenID4VP) Guide.
How each binds a remote response to the verifier differs. For mdoc over OpenID4VP, the wallet signs a DeviceAuthentication structure over the SessionTranscript, whose handover element hashes the client_id, nonce, the verifier's encryption key thumbprint and the response_uri (or, over the Digital Credentials API, the origin, nonce and key thumbprint). For SD-JWT VC, the KB-JWT carries nonce, aud (the client identifier, or origin: plus the origin over the DC API) and sd_hash. Both stop replay to a different verifier, if the verifier checks them.
Device binding
The ARF defines device binding as the cryptographic link that ties a PID or attestation to the WSCD or keystore in the user's Wallet Unit, preventing copying and enabling user binding (ARF 6.6.3.8). It is called mdoc authentication in 18013-5 and key binding in SD-JWT VC (OIA_02).
| Aspect | mdoc | SD-JWT VC |
|---|---|---|
| Holder key location in credential | deviceKeyInfo.deviceKey in the MSO (COSE_Key) | cnf claim, a JWK under HAIP |
| Proof at presentation | deviceSigned signature or MAC over DeviceAuthentication | KB-JWT signed by the holder key |
| Required by base standard | Yes | No, optional |
| EUDI rule | Mandatory for PID and all 18013-5 attestations | Recommended; mandatory for PID; KB-JWT always present for holder-bound credentials (HAIP 6.1.1.1) |
| Verifier control | Always present | require_cryptographic_holder_binding (default true in OpenID4VP 6.1) |
| Transaction data | Signed inside device authentication | transaction_data_hashes in the KB-JWT |
The weak point is the verifier, not the format. OpenID4VP Section 5.3 states that a verifier that requests a presentation without holder binding "accepts that the presented Credential may have been replayed". The ARF also notes that verifying the device binding signature is recommended rather than mandatory for relying parties. Treat it as mandatory in your own policy for anything above low assurance. The keys themselves and their attestation are covered in the Wallet Unit Attestation and Device-Bound Keys Guide.
Unlinkability limits
Selective disclosure hides attributes; it does not hide the credential. ARF Section 7.4.3.5 explains that attestations contain "unique, fixed elements such as hash values, salts, public keys, and signatures" that relying parties could store and compare. This applies equally to the MSO signature and device key in an mdoc and to the JWT signature, digests and cnf key in an SD-JWT VC.
- Relying party linkability: one verifier, or several colluding, link presentations of the same credential. The ARF mitigation is issuing many technical attestations for one logical attestation. Wallet Solutions must support method A, once-only attestations, and method B, limited-time attestations; method C, rotating batches, and per-relying-party attestations are optional. The ARF also expects relying parties to discard unique elements once no longer needed.
- Attestation provider linkability: verifiers share values with the issuer, who recognises its own signatures. The ARF states this cannot be fully eliminated with salted-hash formats; zero-knowledge proofs are the only viable mitigation, and no ZKP has yet been selected (Technical Specifications 4, 13 and 14 are the working documents). The OpenWallet Foundation Multipaz project integrates the Longfellow-ZK library against the 18013-5 second edition draft. See the Zero-Knowledge Proofs Guide.
- Status lists: HAIP requires a unique, unpredictable status list index per SD-JWT VC, because a shared or sequential index is itself a correlation handle. Apply the same thinking to mdoc revocation identifiers. See the Token Status List and Credential Revocation Guide.
Batch size, validity period and status design decide linkability far more than CBOR versus JSON.
EUDI ARF requirements in one place
| ARF requirement | What it says | Effect on format choice |
|---|---|---|
| 5.4.1 and Topic 12 | Wallet Units support 18013-5 and SD-JWT VC; W3C VCDM optional | Wallets carry both; issuers choose per rulebook |
| PID_02 | PID issued in both 18013-5 and SD-JWT VC format | PID verifiers can pick either |
| Topic 12 formats (QEAA, PuB-EAA) | Rulebook specifies one or more of mdoc and SD-JWT VC | Check each rulebook before building |
| Topic 12, SD-JWT VC profile | SD-JWT VC attestations comply with HAIP Section 6.1 | Verifiers implement HAIP, not the raw draft |
| Topic 12, offline proximity | Attestations needed offline in proximity use mdoc | Counter and roadside use cases need mdoc |
| OIA_01, ProxId_01, ProxId_01a | Wallets support 18013-5 proximity; relying party proximity optional | Only build proximity if you meet people in person |
| OIA_02 and 6.6.3.8 | Wallets prove device binding per either standard | Verifiers should request and check it |
| 7.4.3.5 | Once-only and limited-time attestations supported | Expect many technical credentials per user |
Requirement identifiers change between ARF releases. The framework is covered in the EUDI Wallet Architecture and Reference Framework Guide and the legal basis in the eIDAS 2.0 and the European Digital Identity Framework Guide.
Threat model and failure modes by format
mdoc
- Reader trust gaps: an in-person verifier that does not check the document signer chain against the correct issuing authority roots will accept any well-formed MSO.
- Stale offline data: offline readers cannot fetch status, so they rely on
validUntil. Long MSO validity means a revoked credential stays usable at offline counters. - Over-asking in proximity: requesting a full data set when
age_over_18suffices exposes portrait and address, even though wallets warn users about over-asking. - Parser risk: hand-written CBOR and COSE decoders are a common bug source. Use a maintained library and fuzz your integration.
SD-JWT VC
- Accepting unbound presentations: the format allows credentials without
cnf. A verifier that does not require key binding accepts copied credentials. - Weak KB-JWT checks: skipping
nonce,aud,iatorsd_hashvalidation opens replay and splicing. - Issuer key discovery abuse: resolving issuer metadata or remote key URLs from untrusted input creates SSRF exposure; HAIP narrows this by mandating
x5c. - Draft drift: libraries built for an older draft fail against current wallets. Pin to HAIP and test against the wallets you must accept.
Both formats share wallet-side threats such as fraudulent issuance and account takeover of the wallet itself; see the Digital Identity Wallet Fraud Risks Guide.
Relying party implementation burden
| Task | mdoc | SD-JWT VC |
|---|---|---|
| Parse credential | CBOR, tagged byte strings, COSE_Sign1 | Split on tildes, base64url, JSON, JWS |
| Verify issuer | Validate x5chain to an issuing authority root, check MSO validity | Validate x5c chain (HAIP), check exp |
| Verify disclosures | Hash each IssuerSignedItem, match valueDigests by namespace and digestID | Hash each disclosure, match _sd digests, reject duplicates |
| Verify holder | Rebuild SessionTranscript, verify device signature or MAC | Verify KB-JWT signature with cnf key, check nonce, aud, sd_hash |
| Check status | MSO status (second edition mechanism) | Fetch and cache status list token, read index |
| Request syntax | DCQL query for the mdoc docType, or an 18013-7 request | DCQL with vct_values (required) |
| In-person hardware | NFC or BLE reader app or device | Not applicable |
Online relying parties already running OpenID Connect reuse JOSE libraries, JAR signed requests and direct_post.jwt handling for SD-JWT VC; adding mso_mdoc on the same OpenID4VP endpoint mainly adds CBOR and COSE verification and SessionTranscript construction. HAIP applies to both: x509_hash client identifiers, the trusted_authorities query, and ECDH-ES P-256 response encryption. See the Relying Party Integration with Digital Identity Wallets Guide.
When to choose each
- Choose mdoc first when: you verify people in person (counters, roadside checks, venues, pharmacies), connectivity is unreliable, the credential is an mDL, or you must accept mobile driving licences issued outside the EU ecosystem that are only issued as mdocs.
- Choose SD-JWT VC first when: every interaction is online, your engineering team is web and JOSE based, you want readable payloads for support and audit, or the attestation rulebook you depend on is SD-JWT VC only.
- Support both when: you are an issuer of PID or a widely used attestation, you run both channels, or you cannot predict which wallets your users hold.
Small versus large organisations: a small online relying party can start with one format through a certified verifier service or library and add the second later, since PID is issued in both. A bank, telecom operator or government service with branches should plan for both from the start, because the branch channel forces mdoc and the app channel favours SD-JWT VC.
Worked scenario
A mid-sized bank wants to use the EUDI Wallet PID for account opening in its app and in branches, and later accept a professional qualification attestation.
- App onboarding: the bank requests PID claims with DCQL through the Digital Credentials API, asking for
dc+sd-jwtwithvct_valuesofurn:eudi:pid:1, and also acceptingmso_mdocas an alternative.require_cryptographic_holder_bindingstaystrue. The verifier checks thex5cchain, disclosures, KB-JWTnonce,audandsd_hash, and status. - Branch onboarding: staff tablets run an mdoc reader. The customer taps or scans; the reader requests only the PID elements needed for customer due diligence from
eu.europa.ec.eudi.pid.1, verifies the document signer chain against the trusted list held on the tablet, and verifies mdoc authentication. Trust anchors refresh daily. - Qualification attestation: before building, the bank reads the attestation rulebook. If it specifies SD-JWT VC only, branch staff send customers a same-device online flow instead of using the reader.
- Privacy: the bank stores the verified attribute values and a verification record, and discards digests, signatures and device public keys after verification, in line with ARF 7.4.3.5.
How to implement
- Inventory and read rulebooks: list each verification by channel (in person, same-device online, cross-device online), then record which formats each attestation rulebook allows and whether offline proximity is required.
- Pin versions: record OpenID4VP 1.0, HAIP 1.0, the SD-JWT VC draft your libraries implement, ISO/IEC 18013-5:2021, TS 18013-7:2025 and the ARF release.
- Pilot one format online: run in a test environment against the EU reference wallet and the wallets you must accept, with negative tests: missing key binding, wrong
aud, reused nonce, expired MSO, revoked status, untrusted issuer. - Add the second format: extend DCQL to accept both, keep identical policy (binding, status, minimum claims) for each.
- Add proximity if needed: pilot readers in one location, test offline behaviour and trust list refresh.
- Roll back safely: keep the previous identity verification route live until each wallet flow reaches target success rates; switch formats by configuration in the DCQL query, not by code release.
Detection and measurement
- Log per presentation: format, issuer certificate identifier, binding result, status result, claims requested and claims received, and failure reason. Do not log the digests, salts or device keys you intend to discard.
- Verification success rate by format and wallet: a drop after a wallet update usually signals draft or profile drift.
- Unbound presentation rate: should be zero for any flow above low assurance.
- Status check coverage: share of online presentations with a fresh status result; for offline readers, age of the oldest trust list on a device.
- Replay rejects: reused nonces or
audmismatches.
Common failure patterns
- Building for one format: an online-only SD-JWT VC verifier later finds its branch channel needs mdoc, or the reverse.
- Convenience over binding: setting
require_cryptographic_holder_bindingtofalseto raise pass rates, which accepts copied credentials. - Raw draft instead of profile: implementing whatever SD-JWT VC draft a library ships rather than HAIP Section 6.1.
- Equating selective disclosure with anonymity: keeping signatures and digests in data stores, which turns the relying party into a tracking database if breached.
Framework mapping
| Framework | Reference | Relevance |
|---|---|---|
| NIST CSF 2.0 | PR.AA-02 | Identities proofed and bound to credentials: device binding and issuer trust |
| NIST CSF 2.0 | PR.AA-03 | Users authenticated: holder proof at presentation |
| NIST CSF 2.0 | PR.DS-02 | Data in transit protected: session encryption and response encryption |
| NIST SP 800-53 Rev. 5 | IA-8 | Identification and authentication of non-organisational users, such as customers presenting wallet credentials |
| NIST SP 800-53 Rev. 5 | IA-5 | Authenticator management: issuer and device keys, validity, revocation |
| NIST SP 800-53 Rev. 5 | SC-13, SC-23 | Cryptographic protection and session authenticity: ES256, SessionTranscript and KB-JWT binding |
| NIST SP 800-53 Rev. 5 | PT-2 | Authority to process PII: request only the claims the purpose needs |
Practitioner checklist
- Map every verification to a channel and record the formats each attestation rulebook allows.
- Accept both
mso_mdocanddc+sd-jwtfor PID unless a channel rules one out. - Require cryptographic holder binding for every flow above low assurance and verify it.
- Implement SD-JWT VC to HAIP Section 6.1 and record the draft version your library supports.
- Validate issuer chains against the correct trust lists and refresh offline readers on a schedule.
- Check status online and keep credential validity short where offline use is expected.
- Request the minimum claims, and discard digests, salts, signatures and device keys after verification.
- Run negative tests for replay, wrong audience, missing binding, expiry and revocation before go-live.
Standards and references
- ISO: ISO/IEC 18013-5:2021 Mobile driving licence (mDL) application
- ISO: ISO/IEC TS 18013-7:2025 mDL add-on functions
- IETF: SD-JWT-based Verifiable Digital Credentials (SD-JWT VC), Internet-Draft
- OpenID Foundation: OpenID4VC High Assurance Interoperability Profile 1.0
- OpenID Foundation: OpenID for Verifiable Presentations 1.0
- European Commission: EUDI Wallet ARF, Data model and data exchange protocols
- European Commission: EUDI Wallet ARF Annex 2 High-Level Requirements by Topic
- OpenWallet Foundation: Multipaz mdoc and SD-JWT VC libraries
Related NHI Mgmt Group resources: Digital Identity Wallets Guide · Mobile Driving Licence (mDL) Guide · Decentralised Identity vs Federated Identity · OpenID for Verifiable Credential Issuance Guide