PS256 JWT Algorithm
PS256 uses RSA-PSS (Probabilistic Signature Scheme) with SHA-256. RSA-PSS is the modern, provably-secure alternative to PKCS#1 v1.5 used by RS256. It employs randomized padding (a salt) that eliminates the theoretical Bleichenbacher attack surface present in RS256, while using the same RSA key infrastructure.
Key Requirements
RSA key pair of at least 2048 bits — same key format as RS256. RSA-3072 or RSA-4096 recommended for new systems. Existing RS256 keys can be reused for PS256.
JWT Header
Every JWT using PS256 has this header (base64url-encoded as the first segment):
{
"alg": "PS256",
"typ": "JWT"
}Code Examples
Node.js — Sign (jose library)
import { SignJWT, importPKCS8 } from 'jose'
// Same PEM key format as RS256 — no key change needed
const privateKey = await importPKCS8(process.env.RSA_PRIVATE_KEY!, 'PS256')
export async function signToken(payload: Record<string, unknown>) {
return new SignJWT(payload)
.setProtectedHeader({ alg: 'PS256' })
.setIssuedAt()
.setExpirationTime('1h')
.sign(privateKey)
}Node.js — Verify (jose library)
import { jwtVerify, importSPKI } from 'jose'
const publicKey = await importSPKI(process.env.RSA_PUBLIC_KEY!, 'PS256')
export async function verifyToken(token: string) {
const { payload } = await jwtVerify(token, publicKey, { algorithms: ['PS256'] })
return payload
}Python — PyJWT
import jwt
from cryptography.hazmat.primitives import serialization
with open("private.pem", "rb") as f:
private_key = serialization.load_pem_private_key(f.read(), password=None)
with open("public.pem", "rb") as f:
public_key = serialization.load_pem_public_key(f.read())
# PyJWT 2.x supports PS256
token = jwt.encode({"sub": "1234"}, private_key, algorithm="PS256")
payload = jwt.decode(token, public_key, algorithms=["PS256"])When to Use PS256
Preferred over RS256 for all new systems that must use RSA-family algorithms. Same key infrastructure as RS256 (no key migration needed), with improved security properties. Use when you need asymmetric JWT signing but a policy or dependency requires RSA over EC.
Security Considerations
RSA-PSS is provably secure under the random oracle model. The salt length should equal the hash output length (32 bytes for SHA-256 — 'saltLength: 32' in OpenSSL). Avoid 'saltLength: recover' or zero-length salts which weaken the security proof.
Related Algorithms
Standardised in RFC 7518 §3.5 — JSON Web Algorithms (JWA).
Decode a real JWT
Paste any JWT into the debugger to inspect the header, payload, and verify an PS256 signature.
Open JWT DebuggerFrequently Asked Questions
Why should I use PS256 instead of RS256?
RSA-PSS (PS256/PS384/PS512) uses probabilistic padding that is provably secure under the random oracle model. RS256's PKCS#1 v1.5 padding has known theoretical vulnerabilities (Bleichenbacher's attack). For new systems, PS256 is preferable to RS256 while reusing the same key infrastructure.
Can existing RS256 keys be reused for PS256?
Yes. PS256 uses the same RSA key format as RS256. You can migrate from RS256 to PS256 by changing the 'alg' field in the JWT header and updating your signing code — no key rotation required.
What salt length should I use with RSA-PSS?
The salt length should equal the hash output length: 32 bytes for PS256 (SHA-256), 48 bytes for PS384, 64 bytes for PS512. This maximises the security proof. The jose library uses the correct salt length by default.
