Selective Disclosure with SD-JWT: Prove You're Over 18 Without Showing Your Passport
To prove you're old enough to buy a drink, you hand over a document showing your full name, exact birth date, address, document number, and photo, all to a stranger who needed exactly one bit of information. Online, it's worse: the bar keeps a copy. SD-JWT is the standard built to end that, and it's simpler than it sounds.
The over-sharing problem
Almost every identity check today is all-or-nothing. The website needs to know you're over 18; you upload your entire passport. The platform needs your country of residence; it gets your full address history. Each business that collects the full document becomes another database of identity data waiting to be breached. The user has no way to share less, because the document itself doesn't come apart.
That is the actual problem: credentials are signed as a unit. Cross out the fields you'd rather not share and you break the signature, so verifiers demand the whole thing. Selective disclosure is the fix: a credential format where individual claims can be revealed or withheld without breaking the issuer's signature.
How SD-JWT works, conceptually
SD-JWT stands for Selective Disclosure JWT, an extension of the JSON Web Token format that most developers already know. The mechanism rests on one idea: the issuer signs fingerprints of your claims instead of the claims themselves.
Here's the flow, without the math:
- At issuance, the issuer takes each claim (name, birth date, nationality), adds a random salt to it, and computes a hash (a short, unique fingerprint). The signed token contains only these fingerprints. The actual claim values travel alongside as separate "disclosure" pieces that the holder keeps in their wallet.
- At presentation, the holder sends the signed token plus only the disclosures they choose to reveal. Proving age? Attach the birth-date disclosure (or an "over 18" claim, if the issuer included one) and withhold everything else.
- At verification, the verifier hashes each disclosure it received and checks that the fingerprint appears in the signed token. Match means the claim is exactly what the issuer attested, unmodified and unforged, even though the verifier never saw the claims that stayed hidden.
The random salt matters: it stops a verifier from guessing hidden values by hashing candidates ("does this fingerprint match 'born 1990-01-01'?"). With a salt attached, identical values produce different fingerprints every time.
The result: one credential, issued once, that can answer many different questions while revealing only what each question requires.
Holder binding: why a stolen credential is useless
Selective disclosure alone has a gap. If someone copies your credential, what stops them from presenting it as their own?
SD-JWT addresses this with holder binding (key binding). At issuance, the credential is tied to a cryptographic key that lives in the holder's wallet, typically in the device's secure hardware. At presentation time, the holder signs a fresh, verifier-specific challenge with that key, proving they control the key the credential was issued to.
This kills two attacks at once. A thief who exfiltrates the credential can't present it, because they don't have the device key. And a malicious verifier can't replay a presentation it received to impersonate the user elsewhere, because each presentation is bound to a specific verifier and moment. It's the difference between a photocopy of a passport and a passport with a chip that answers challenges.
SD-JWT is not zero-knowledge, and that's fine
A common conflation worth untangling: SD-JWT is selective disclosure, not zero-knowledge proof.
With SD-JWT, the claims you reveal are revealed in full. Proving you're over 18 by disclosing your birth date shows the verifier your actual birth date. A zero-knowledge proof can do something stronger: prove a predicate ("this birth date is more than 18 years ago") without revealing the date itself, and advanced schemes can make repeated presentations unlinkable to each other.
In practice the gap is narrower than it sounds. Issuers can include precomputed claims like age_over_18 directly in
the credential, so the holder discloses a boolean rather than a birth date: predicate-style privacy through credential
design rather than novel cryptography. ZKP-based credential schemes are an active research and standardization area and
may well layer into this ecosystem over time. But SD-JWT works today, builds on JWT infrastructure every backend team
already runs, and covers the overwhelming majority of real-world data-minimization needs. The honest framing: SD-JWT is
the pragmatic 90% solution; ZKPs are the frontier.
Standardization and the EUDI bet
SD-JWT was developed in the IETF, the body behind the core JWT standards, and is advancing through the IETF standardization process, alongside a companion specification (SD-JWT VC) that profiles it for verifiable credentials. The format is already implemented across open-source wallet and verifier libraries in multiple languages.
Its highest-stakes endorsement came from Europe: the EUDI Wallet's Architecture and Reference Framework selected SD-JWT-based credentials as a core format for person identification data, alongside ISO mdoc. The reasons are pragmatic. SD-JWT extends formats and crypto that existing infrastructure already understands, it is auditable and simple enough for security certification, and it delivers the data-minimization properties that eIDAS 2.0 legally requires. When the world's largest digital identity deployment picks a format, the ecosystem follows: tooling, wallets, and verifier support are accreting around SD-JWT fast.
It also slots cleanly into the broader open stack: W3C Verifiable Credentials define the conceptual issuer-holder-verifier model, OpenID4VC protocols move credentials around, and SD-JWT is one of the concrete formats on the wire.
What this means for age verification UX
Age checks are where selective disclosure gets its clearest product win. Regulation is pushing platforms toward verifying age, while users rightly refuse to upload passports to social networks. SD-JWT dissolves that tension.
The flow becomes: a credential with an over-18 attestation already sits in your wallet, issued once by a party that verified you properly. A site requests proof of age; your wallet shows exactly what will be shared, "over 18: yes," nothing else; you approve with a tap. The site gets a cryptographically verifiable answer and stores no document, no birth date, no name. Verification drops from a minutes-long document upload to a seconds-long consent screen, and the platform's data-breach liability for that flow drops toward zero.
That same pattern (verify once, disclose minimally, reuse everywhere) generalizes well beyond age, to KYC status, residency, accreditation, and any attribute a trusted party can attest.
Where OpenKYC fits
OpenKYC is building a reusable KYC marketplace on open standards (W3C Verifiable Credentials, OpenID4VC): verify once, hold the credential in your own wallet, reuse it everywhere, and earn every time it's used. Join the waitlist at openkyc.org.