rfc-9901

Selective Disclosure for JSON Web Tokens

D. Fett, K. Yasuda, B. Campbell
date2025-11 streamIETF areasec wgoauth statusPROPOSED STANDARD pages88 canonicalhttps://www.rfc-editor.org/rfc/rfc9901 doi10.17487/RFC9901
This specification defines a mechanism for the selective disclosure of individual elements of a JSON data structure used as the payload of a JSON Web Signature (JWS). The primary use case is the selective disclosure of JSON Web Token (JWT) claims.

Extracted elements (28)

design-rationale §4.2.1

Disclosure format encoding was intentionally not canonicalized: the digest is computed over the exact base64url-encoded Disclosure string as produced by the Issuer, including any whitespace or Unicode encoding variations. This approach follows the JWS/JWE convention and means the Issuer's choice of encoding is immutably committed by the signature.

jose, json

design-rationale §1

SD-JWT uses a 'salted hashes' approach: instead of including cleartext claim values in the JWT payload, the Issuer places digests of each selectively disclosable claim. During presentation the Holder reveals selected claim values alongside their salts, and the Verifier recomputes and matches the digests. This allows the Issuer signature to cover all claims at issuance while the Holder controls what is revealed.

jose, crypto, privacy

interoperability-note §8

JWS JSON Serialization support is OPTIONAL. When used, Disclosures are placed in the `disclosures` unprotected header parameter as an array of strings, and the KB-JWT (if present) is in the `kb_jwt` unprotected header. In General JSON Serialization, disclosures and kb_jwt MUST appear only in the first unprotected header.

jose, json

normative-requirement §9.7 MUST NOT

An Issuer MUST NOT allow any content critical to evaluating authenticity or validity to be selectively disclosable, including iss, exp, nbf, and cnf. Verifiers MUST ensure that all claims they deem necessary for validity checking are present and disclosed during validation.

jose, security, oauth

normative-requirement §9.3 MUST

Each salt MUST be created as cryptographically random, sufficiently long, and with high enough entropy that guessing is infeasible; the RECOMMENDED minimum is 128 bits. A new salt MUST be chosen independently for each claim, even when the same claim name appears multiple times in the structure.

jose, crypto, security

normative-requirement §7.1 MUST

If any Disclosure was not referenced by a digest value in the Issuer-signed JWT (directly or recursively via other Disclosures), the SD-JWT MUST be rejected. A Holder MUST NOT send a Disclosure that was not included in the issued SD-JWT, and MUST NOT send a Disclosure more than once.

jose, security

normative-requirement §4.1.1 MUST

Implementations MUST support the sha-256 hash algorithm. The hash algorithm identifier in `_sd_alg` MUST be a value from the IANA Named Information Hash Algorithm Registry or another specification/profile of SD-JWT.

jose, crypto, registry

normative-requirement §9.11 SHOULD

SD-JWT applications and profiles SHOULD be explicitly typed using the `typ` JOSE header parameter to prevent cross-JWT confusion attacks, as recommended in Section 3.11 of RFC 8725.

jose, security

normative-requirement §4.2.3 MUST

The digest over a Disclosure MUST be computed over the US-ASCII bytes of the base64url-encoded Disclosure string (not the decoded bytes). The resulting bytes MUST then be base64url-encoded.

jose, crypto

normative-requirement §7.2 MUST

The Holder MUST reject an SD-JWT+KB when it receives an SD-JWT from the Issuer (the Issuer sends only SD-JWTs, not SD-JWT+KBs). For presentation requiring Key Binding, the Holder MUST create a KB-JWT and assemble an SD-JWT+KB.

jose, security

normative-requirement §4.1 MUST

The Issuer-signed JWT MUST be signed using the Issuer's private key and MUST NOT use the `none` algorithm. The Verifier MUST always check the signature; the Issuer-signed JWT MUST be rejected if verification fails.

jose, security, crypto

normative-requirement §7.1 MUST

The same digest value MUST NOT appear more than once in an SD-JWT. If any digest is encountered more than once (directly or via recursive Disclosures), the SD-JWT MUST be rejected.

jose, security

normative-requirement §9.5 MUST NOT

When deciding whether Key Binding is required, Verifiers MUST NOT take into account whether the Holder has provided an SD-JWT+KB or a bare SD-JWT; the Key Binding requirement MUST be determined by the Verifier's own policy before examining the presentation, to prevent an attacker from stripping the KB-JWT.

jose, security, crypto

privacy-consideration §10.4

Decoy digests can be used to pad the number of digests in an SD-JWT, obscuring the actual number of claims. Issuers should weigh this benefit against the additional payload size; consistently padded arrays prevent Verifiers from inferring the total element count.

jose, privacy

privacy-consideration §10.1

SD-JWTs do not inherently provide unlinkability: if the same SD-JWT is presented to multiple Verifiers, or if Verifiers collude, the Issuer-signed JWT can serve as a correlation handle. Unlinkability requires issuing separate SD-JWTs per presentation or applying per-presentation blinding techniques outside the scope of this specification.

jose, privacy

protocol-element §4.2.5

Decoy digests—hashes of random values with no corresponding Disclosure—may be added to `_sd` arrays or inline arrays to obscure the actual number of claims or array elements. No Disclosure is sent for decoy digests, so the Holder sees digests that match nothing.

jose, privacy

protocol-element §4.2.4.1

Digests of selectively disclosable object-property Disclosures are collected into an array under the special key `_sd` at the relevant level of the JSON object. Each `_sd` array entry is a base64url-encoded hash of a Disclosure or a decoy digest; the `_sd` key MUST refer to an array of strings.

jose, json

protocol-element §4.2.4.2

For selectively disclosable array elements, a digest placeholder object `{"...": "<digest>"}` replaces the element in the array. The key MUST always be the three-dot string `...` and the object MUST have no other keys. Verifiers ignore array elements for which no matching Disclosure was provided.

jose, json

protocol-element §4.2.6

Recursive Disclosures allow a selectively disclosable field to itself contain digest placeholders pointing to further Disclosures. If a Disclosure is included in a presentation, all Disclosures necessary to process it (i.e., connect it to the Issuer-signed JWT) MUST also be included.

jose, json

protocol-element §4.3

The Key Binding JWT (KB-JWT) is a standard JWT whose JOSE header MUST set `typ` to `kb+jwt` and whose payload MUST contain `iat`, `aud`, `nonce`, and `sd_hash`. The `sd_hash` value is the base64url-encoded hash of the SD-JWT string (Issuer-signed JWT plus selected Disclosures, tilde-delimited) using the same hash algorithm as the Disclosures.

jose, crypto

protocol-element §4.1.1

The `_sd_alg` claim at the top level of the SD-JWT payload specifies the hash algorithm used to generate Disclosure digests. If absent, the default is sha-256. The claim MUST NOT appear in any nested object.

jose, crypto

registry §11

Section 11.1 registers the `sd_hash` JWT claim in the IANA JSON Web Token Claims registry. Section 11.2 registers two media types: `application/sd-jwt` (SD-JWT compact serialization) and `application/kb+jwt` (Key Binding JWT). Section 11.3 registers the `+sd-jwt` structured syntax suffix.

jose, registry

security-consideration §9.10

SD-JWT integrity: the Issuer-signed JWT is protected by the Issuer's signature, and Disclosure values are protected by their digests. However, the specific set of Disclosures is not integrity-protected; Disclosures can be added or removed while the SD-JWT remains valid. Key Binding guards the selected Disclosure set via sd_hash.

jose, security, crypto

security-consideration §9.4

The hash function used for Disclosures MUST be preimage resistant and computationally hiding (so undisclosed values cannot be inferred from digests), MUST be second-preimage resistant (so forgery of alternate Disclosure values with the same digest is infeasible), and SHOULD be collision resistant to prevent an Issuer from creating multiple Disclosures with the same hash.

jose, crypto, security

security-consideration §9.9

Without Key Binding, an SD-JWT can be replayed by anyone who obtains it—including a malicious Verifier who re-presents a received credential to another Verifier. Issuers and Verifiers in high-sensitivity use cases must enforce Key Binding to limit this forwarding risk.

jose, security, oauth

wire-format §4.2.1

A Disclosure for an object property is a base64url-encoded UTF-8 JSON array of exactly three elements in order: (1) a cryptographically random salt string, (2) the claim name string, (3) the claim value. For an array-element Disclosure, only two elements are used: the salt and the array element value.

jose, json

wire-format §4

The SD-JWT compact serialization is tilde-separated: `<Issuer-signed JWT>~<D.1>~<D.2>~...~<D.N>~`. The Issuer-signed JWT comes first, followed by zero or more Disclosures each trailed by a tilde, and the final element is always an empty string (i.e., the trailing tilde is never omitted).

jose, json

wire-format §4

The SD-JWT+KB compact serialization extends the SD-JWT format by appending a Key Binding JWT: `<Issuer-signed JWT>~<D.1>~...~<D.N>~<KB-JWT>`. The two formats are distinguished by whether the final tilde-separated component is empty (SD-JWT) or a valid KB-JWT (SD-JWT+KB).

jose, json, crypto