Aarunya AppsAarunya Apps

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.

Family
RSA-PSS
Hash
SHA-256
Key type
asymmetric
Performance
Slow (1–10ms)

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 Debugger

Frequently 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.