PS256: RSASSA-PSS with SHA-256 in a JWT
PS256 signs with an RSA key using the probabilistic PSS padding scheme, SHA-256 and MGF1. It is the modern replacement for RS256 and produces a different signature every time, even over identical input.
At a glance
- Algorithm
- PS256, RSASSA-PSS using SHA-256 and MGF1 with SHA-256
- Registered in
- RFC 7518 section 3.5
- Implementation requirement
- Optional
- Key
- RSA key pair, 2048 bits or larger. The same key can be used for RS256.
- Signature size
- Equal to the key size: 256 bytes for a 2048 bit key
- Verified in the decoder
- Yes, in your browser, with a PEM public key.
In detail
PSS differs from the PKCS#1 v1.5 padding used by RS256 in that it mixes random salt into the encoding before the RSA operation. RFC 7518 fixes the salt length at the hash output size, 32 bytes here, and specifies MGF1 with the same hash as the mask generation function. The result is a padding scheme with a security proof that PKCS#1 v1.5 does not have.
The visible consequence is that signing the same token twice gives two different signatures, and both verify. Anything that compares signatures for equality, a deduplication check, a cache key, a test asserting a fixed token string, breaks the moment RS256 becomes PS256. Verification is the only correct way to test a PSS signature, which is a good habit regardless.
Adoption is driven by profiles rather than by breakage. There is no practical forgery against RS256 as used in JWTs today, but financial grade API profiles and several national standards require PS256 or ES256 and forbid the older padding, so the migration is compliance led. Key material carries over unchanged, since a PSS signature uses an ordinary RSA key pair.
The decoder verifies PS256 in your browser given the PEM public key, using the browser's own cryptography. Because the algorithm is optional in RFC 7518 and less widely implemented than RS256, a local check is often the fastest way to tell a genuinely bad signature apart from a verifier that never supported the algorithm in the first place.
Examples
// Header
{ "alg": "PS256", "typ": "JWT" }
// Two signings of identical input, both valid
...header.payload.QWxwaGFTaWduYXR1cmVPbmVTYW1wbGVWYWx1ZQ
...header.payload.QnJhdm9TaWduYXR1cmVUd29TYW1wbGVWYWx1ZQSample values, shortened. PSS salts each signature, so byte comparison of two valid tokens proves nothing.
Things that catch people out
- Asserting on an exact token string in a test. PSS signatures are randomized, so the assertion fails on the second run.
- Assuming a new key is needed. PS256 uses the same RSA key pair as RS256, so a migration is a configuration change on both ends, not a rekey.
- Switching the issuer before every verifier supports it. PS256 is optional in RFC 7518 and older verifiers reject it outright.
Try it: JWT Decoder
Paste a token to decode the header and payload, read the claims and expiry, and verify the signature in your browser. Nothing is uploaded.
JWT Decoder
LOCAL · Browser-OnlyDecode and inspect JSON Web Tokens without sending them to a server
Related JWT claims and algorithms
All jwt claims and algorithms →RS256: RSASSA-PKCS1-v1_5 with SHA-256 in a JWT
RS256 signs a JWT with an RSA private key and verifies with the public key. Key sizes, the RS256 to HS256 confusion attack, and verifying in your browser.
PS384: RSASSA-PSS with SHA-384 in a JWT
PS384 signs a JWT using RSA-PSS with SHA-384 and a 48 byte salt. What changes against PS256, and how the decoder verifies one in your browser.
ES256: ECDSA with P-256 and SHA-256 in a JWT
ES256 signs a JWT with ECDSA on curve P-256 using SHA-256. Signature format, why raw R and S beats DER here, and verifying with a public key.
PS512: RSASSA-PSS with SHA-512 in a JWT
PS512 signs a JWT using RSA-PSS with SHA-512 and a 64 byte salt. Why very small keys cannot carry it, and how verification works in the decoder.
ES384: ECDSA with P-384 and SHA-384 in a JWT
ES384 signs a JWT with ECDSA on curve P-384 using SHA-384. Signature length, where the curve is mandated, and verification in your browser.
ES512: ECDSA with P-521 and SHA-512 in a JWT
ES512 signs a JWT with ECDSA on curve P-521 using SHA-512. Why the curve is 521 bits, what that does to signature length, and how to verify it.
Tools for this
- JWT Decoder Free online JWT decoder - decode and inspect JSON Web Tokens without sending them to a server