1. The Birth of RFC 9901

On November 19, 2025, the specification defining “Selective Disclosure for JSON Web Tokens,” commonly known as SD-JWT (pronounced “ess-dee-jot”), was published as RFC 9901.

It has the following 3 authors:

JSON Web Token (JWT) [RFC 7519] and JSON Web Signature (JWS) [RFC 7515] are Internet standards widely used for ID Tokens and JWT access tokens[RFC 9068].
SD-JWT adds a new capability: letting you extract and show only the necessary parts later.

It can be seen as the formal addition of a new pillar,
“Selective Disclosure,” to the lineage of the JOSE family (JWS / JWT / JWE).


2. What Is SD-JWT For?

2-1. The Problem with Conventional JWTs: “On-Demand Issuance” or “Everything Included”

The conventional JWT model essentially passes a “signed block of JSON” to a service as-is.

  • The issuer (an IdP or authorization server) bundles user information into a JWT
  • The receiving service (relying party) can read everything in it

A model such as OpenID Connect, which issues credentials dynamically on demand, can provide selective disclosure, data minimization, and unlinkability between RPs (RP+RP’-U Unlinkability), typically by using a PPID (Pairwise Pseudonymous Identifier). None of these, however, can be achieved when the goal is to issue a credential in advance, before its purpose is known, store it, and use it later.

For example, if “age,” “address,” “name,” and “email address” are contained in 1 JWT, a service may really need to know only whether the user is at least 20 years old. Yet when a pre-issued, stored JWT is used, the service also sees the address and name.

This “everything included” structure is simple to implement, but when credentials are to be stored and used later, it

  • cannot support selective disclosure and therefore cannot satisfy the data-minimization principle
  • cannot satisfy RP+RP’-U Unlinkability either

These were its limitations. (They are, of course, a tradeoff for simplicity of implementation.)

2-2. Compatibility with the Wallet Model

There are genuine use cases for storing something and using it later. Typical examples include use where there is no network signal or presenting a diploma after the issuing school has closed. You may wonder how often there is no signal, but that reflects Japan’s fortunate environment. Reception inside stone buildings in Europe can be dismal, and even outdoors in a major city such as Mannheim it may disappear just a short distance from a station. The same is naturally true across the vast United States. Perhaps partly for this reason, recent identity wallets such as the European EUDI Wallet assume a model in which

  • 1 wallet (a smartphone app) stores multiple Verifiable Credentials (VCs), and
  • the user chooses to present “only this item to this service”

This means the wallet and issuer need to be connected ONLINE only during issuance.

What is needed here is

“a format that lets you later select and safely show only part of a single stored piece of signed data”

That is what the SD-JWT specification in RFC 9901 defines.


3. SD-JWT in a Nutshell

In very broad terms, SD-JWT works as follows.

  1. It is based, as before, on a signed JWT (JWS)
  2. For some claims, however, the JWT contains “only a hash value
  3. A Disclosure containing the original value and salt is kept separately and given to the Verifier only when needed
  4. The Verifier
    • recalculates the hash from the Disclosure,
    • checks whether it matches the hash in the signed JWT, and thereby
    • confirms that it is indeed part of data signed by the Issuer

To prevent improper transfer of a token, there is also a mechanism that binds the token to the user’s key pair (Key Binding).
The combined structure is called SD-JWT+KB.


4. The 3 Parties and the SD-JWT Flow

The basic parties in SD-JWT are the same as in the VC world.

  • Issuer
    An organization responsible for the facts, such as a government office, bank, or university.
  • Holder
    The user. Holds credentials in a smartphone wallet app.
  • Verifier
    A service provider, such as for opening a bank account, verifying age, or controlling entry.

A typical flow is as follows.

  1. Issuance
    • The Issuer assembles user attributes (such as an address and date of birth) into JSON
    • For “items to be selectively disclosed later,” it
      calculates a hash from the value + a random salt and embeds only that hash in the JWT
    • The original value + salt are prepared separately as a Disclosure
    • The signed JWT and multiple Disclosures are bundled as an “SD-JWT” and given to the Holder
  2. Presentation
    • The user attempts to use a service
    • The wallet selects from the SD-JWT only the Disclosures for the items to be shown to the Verifier
    • It sends the signed JWT + selected Disclosures + (if needed) a Key Binding JWT to the Verifier
  3. Verification
    • The Verifier
      • verifies the JWT signature with the Issuer’s public key
      • uses each Disclosure to recalculate its item’s hash and confirms that it matches the hash in the JWT
    • This protects undisclosed items while confirming that the disclosed item is part of data signed by the Issuer

5. A Slightly Technical Discussion: Salts and Disclosures

5-1. Selective Disclosure Using Salted Hashes

For each claim (such as an address or birthday),

  • salt + value + (in some cases, the claim name)

are hashed, and the resulting hash value is embedded in the JWT.

When the claim is actually disclosed, the Disclosure supplies

  • “salt, claim name, and value”

to the Verifier.

The Verifier recalculates the hash in the same way and checks whether it matches the hash in the JWT to detect tampering.
Because a salt is included, the values of undisclosed claims are harder to guess.

5-2. Disclosures as “Disclosure Components”

The RFC defines a Disclosure as a Base64url-encoded JSON array, for example:

  • Element 0: salt
  • Element 1: claim name (sometimes omitted for an array element)
  • Element 2: claim value

Inside a wallet, it helps to picture this as

“holding one large credential as a collection of fine-grained Disclosures and extracting and sending only those that are needed.”

This is an easy way to understand the concept.

5-3. Key Binding and SD-JWT+KB

SD-JWT alone leaves the risk of an attack in which someone copies a token and presents it as their own (a replay attack).
RFC 9901 therefore defines Key Binding, which binds an SD-JWT to the Holder’s key pair.

  • Include the Holder’s public key (or a reference to it) in the SD-JWT
  • At presentation time, the Holder also sends a Key Binding JWT (KB-JWT) signed with that key
  • The Verifier
    • checks that the SD-JWT and KB-JWT are bound to the same key
    • verifies that the Holder actually possesses the private key

Requiring Key Binding in SD-JWT+KB increases resistance to copied VCs.

Note: Holder Binding includes Key Binding, Claim Binding, and Biometrics Binding. +KB implements Key Binding. With Key Binding, however, impersonation remains possible if the medium holding the key, such as a device, is transferred to someone else; this is known as an Alice-to-Bob Attack. Buying and selling bank accounts is a prime example. Preventing this generally requires Biometrics Binding.

5-4. Support for JSON Structures and Arrays

RFC 9901 covers not only simple, flat JSON but also

  • nested objects
  • disclosure of individual array elements
  • concealing patterns with “dummy hashes (Decoy Digests)”

It defines support for these cases as well.

This makes it possible to

  • avoid revealing that every person’s credential has exactly the same structure
  • reduce the risk of tracking based solely on the number of disclosed items

These are some of the techniques it enables.


6. SD-JWT, VCs, and Identity Wallets

6-1. SD-JWT VC: Its Role as a VC Format

At the IETF, using SD-JWT from RFC 9901, a specification for representing Verifiable Credentials is being developed as the
“SD-JWT-based Verifiable Credentials (SD-JWT VC)” draft.

Its role is to

  • take a JSON-formatted VC,
  • make selective disclosure possible with SD-JWT, and
  • define how it is verified

The specification is currently under WG review before entering WG Last Call. As a reviewer, I have also proposed about 28 editorial improvements (though some might be considered technical): breaking up the long sentences common in writing by Americans and Germans, clarifying who must act where excessive passive voice makes that ambiguous, and adding security, privacy, and equity considerations. To validate the examples in the draft specification, I also created “sd-jwt-decoder,” a static HTML/JavaScript page for decoding and verifying SD-JWTs.It is also on GitHub (it is a single 1-page HTML file, so it can easily run locally—which I needed to validate the draft on an airplane); please send a pull request if you find a bug.

6-2. Use in the EUDI Wallet

The European Commission’s EUDI Architecture Reference Framework (ARF) indicates that the European Digital Identity Wallet will combine standards including

  • OpenID for Verifiable Credentials (OpenID4VCI / OpenID4VP)
  • SD-JWT / SD-JWT VC
  • the mobile driving licence (mDL) from ISO/IEC 18013-5

These are to be used in combination.

In this context, RFC 9901 is positioned as

“the core format for implementing, on a
JWT/JOSE basis, VCs stored in identity wallets such as the EUDI Wallet”

That is its role.

6-3. Benefits for Wallet Users

For an ordinary user, the experience might look like this.

  • Age verification
    At a convenience store, present only whether the person is at least 20 years old, rather than their date of birth
  • Address verification
    Show an online retailer only the address needed for delivery, without revealing other attributes
  • Identity verification (KYC)
    Present only the required combination of attributes to a bank or securities company, and reuse the same VC with other services

All of these are enabled by SD-JWT’s ability to break 1 piece of signed data into fine-grained parts and extract only what is needed.


7. The Expanding Ecosystem (Overview)

Multiple open-source and commercial solutions are already incorporating SD-JWT / SD-JWT VC.

  • SD-JWT support in various wallet frameworks: one example is wwWallet from the Siros Foundation, where I serve as a director.
  • SD-JWT VC issuance endpoints provided by Authlete and others
  • Adoption in the EUDI Wallet project and SPRIND initiatives
  • Development by the OpenID Foundation of the High Assurance Interoperability Profile (HAIP), combining OpenID4VC and SD-JWT VC

RFC 9901 is positioned as one of the foundational pieces beneath these developments.


8. Summary

  • RFC 9901 is an Internet standard that gives JWT / JWS the capability of selective disclosure.
  • SD-JWT defines a format that
    • places only hashes in the signed JWT,
    • presents original values and salts as Disclosures only when needed, and
    • still preserves authenticity through the Issuer’s signature
      .
  • Adding Key Binding in SD-JWT+KB enables secure presentations bound to the wallet owner.
  • Together with the SD-JWT VC draft, the EUDI ARF, and OpenID4VC profiles, it will be used as
    one of the core formats for VCs stored in identity wallets.

A new piece has joined the JOSE / JWT lineage, clarifying one practical implementation pattern for wallet-based digital identity infrastructure.

Related posts

JWS and JWT Are Now RFCs!

It took a very long time[1], but JSON Web Signature (JWS) and JSON Web Token (JWT) have finally become Standards Track RFCs[2]. They are [RFC 7515]…

OAuth · 2015-05-20