skip to content

In a JWT, what practical differences decide between RS256, PS256 and ES256?

level: seniorimportance: should knowfreq 33%

answer

  1. Two RSA options, one elliptic-curve option
  2. Signature length differs by a factor of four
  3. The least capable consumer decides
  4. Padding scheme versus curve
  5. Accept only what you issue

basics

~20 s

All three are asymmetric JWS algorithms. ES256 produces a far smaller signature than the two RSA options, so tokens are shorter; RS256 has the widest library and platform support; PS256 uses the modern RSA padding on the same RSA key pair but is less universally implemented.

solid answer

~50 s

The three identifiers come from RFC 7518. `RS256` is RSASSA-PKCS1-v1_5 with SHA-256 — the de facto default, supported by essentially every JWT library and every KMS. `PS256` is RSASSA-PSS with SHA-256, the modern RSA signature padding; it uses the same kind of RSA key pair, so migrating is a signer-side and verifier-side change rather than a new key type, but older libraries may not support it. `ES256` is ECDSA on curve P-256 with SHA-256; its signature is 64 bytes against roughly 256 bytes for a 2048-bit RSA signature, which visibly shortens tokens that ride in headers and cookies where gateways enforce size limits. In practice you decide on three things: what every consuming library and HSM supports, how much token size matters in your transport, and whether your organisation's crypto policy calls for PSS or elliptic curves. Whatever you pick, verifiers must pin it.

code

text · 5 lines
text
RS256  RSASSA-PKCS1-v1_5 + SHA-256   sig ~256 B (RSA-2048)
PS256  RSASSA-PSS + SHA-256 (MGF1)   sig ~256 B (RSA-2048)
ES256  ECDSA P-256 + SHA-256         sig   64 B
ES384  ECDSA P-384 + SHA-384         sig   96 B
ES512  ECDSA P-521 + SHA-512         sig  132 B

go deeper

for a junior

Recall that all three are asymmetric algorithms with a private signing key and a public verification key, and that ES256 produces noticeably shorter tokens.

for a middle

Explain the concrete differences you can observe: signature length, key representation in a JWK, and which algorithm identifiers pair with which key types.

for a senior

Drive the decision from consumer support, transport size limits, and signing infrastructure, and make sure the verifier accepts only the algorithms you actually issue.

for a principal

Own the standard across the estate: which algorithms are permitted, how a change is rolled out with an overlap window, and whether policy mandates PSS or elliptic curves.

## The three identifiers RFC 7518 registers the JWS algorithm names. The asymmetric families relevant here: - **`RS256` / `RS384` / `RS512`** — RSASSA-PKCS1-v1_5 with the named SHA-2 hash. - **`PS256` / `PS384` / `PS512`** — RSASSA-PSS with the named hash and MGF1 using the same hash. - **`ES256` / `ES384` / `ES512`** — ECDSA with, respectively, curves P-256, P-384, and P-521 and the matching hash. Note that `ES512` pairs with P-521, not a "P-512" curve, which does not exist. RFC 8037 adds `EdDSA`, used with Ed25519 or Ed448 keys and represented with a `kty` of `OKP` in a JWK. It is a later addition and support varies, so treat it as a deliberate choice rather than a default. ## Signature and key size, which is what you feel This is the difference with the most visible operational consequence. A signature made with a 2048-bit RSA key is 256 bytes; Base64url-encoded that is roughly 342 characters of the token. An `ES256` signature is 64 bytes — the two fixed-width components concatenated — which is about 86 characters. A 4096-bit RSA key doubles the RSA figure again. Tokens travel in `Authorization` headers and cookies, and gateways, load balancers, and application servers all impose header-size limits. A claim-heavy token signed with RS256 plus a long key identifier can approach those limits; the same token under ES256 has a few hundred bytes of headroom. Public keys follow the same pattern in the JWKS document, which matters less but is not nothing when the set is fetched frequently. ## Ecosystem support, which is what actually decides it `RS256` is the algorithm every JWT library implements, every managed identity provider defaults to, and every KMS and HSM can sign with. If a token is consumed by third parties, unfamiliar SDKs, or old runtimes, that ubiquity is a real argument. `ES256` support is now broad but not universal, especially in older libraries and in some hardware-backed signing paths. `PS256` is the thinnest of the three in practice, since many implementations added PSS later than the other two. The rule of thumb: the algorithm must be supported by *every* consumer, and the least capable consumer decides. Discovering after rollout that one partner's library cannot verify `PS256` means an unplanned rotation back. ## RS256 versus PS256 Both are RSA signature schemes over the same kind of key pair, which is what makes the comparison interesting: an issuer can often switch padding without generating a new key type. PSS is the padding scheme that modern cryptographic guidance prefers, and some regulatory or internal policies specify it. RS256's PKCS#1 v1.5 padding is not considered broken for signatures, so this is usually a policy and hygiene decision rather than an urgent remediation. Note that even though the key pair type is the same, the `alg` value changes, so it is still a coordinated rollout with a new `kid` and an overlap window. ## Performance, stated carefully The honest framing for a token system: with RSA, signing is the expensive operation and verification is comparatively cheap, so RSA concentrates cost at the issuer. With ECDSA the two operations are closer together, with signing cheaper than RSA signing. Either way, for a typical API a single signature verification is small next to the network and database work in the same request, so performance is rarely the deciding factor. Where it does show up is at a high-volume token issuer signing thousands of tokens per second, or in a KMS-backed setup where every signature is a billed remote call. ## Choosing, and then locking it in A defensible answer: default to `RS256` when interoperability with unknown consumers dominates; choose `ES256` when you control the consumers and token size matters; choose `PS256` when a policy requires PSS and you have verified every consumer supports it. Then configure verifiers to accept exactly the algorithms you issue, and treat the header's declared algorithm as a value to check against configuration rather than a value to obey. Supporting a broad set of algorithms "for flexibility" enlarges the surface for no benefit — every accepted algorithm is one more path an attacker can try to steer verification down.

  • If you migrate from RS256 to ES256, what has to change beyond the issuer's configuration?
    A new key pair with a new `kid` and a `kty` of `EC` goes into the JWKS, and every verifier must accept `ES256` and support elliptic-curve keys before you switch. It is the same publish-wait-switch-retire overlap as any rotation, with the extra check that each consumer's library actually implements the algorithm.
  • Why should a verifier not simply accept any algorithm listed in the JWKS?
    Every accepted algorithm is a path verification can be steered down by attacker-supplied header content. The safe configuration names the small set the issuer actually uses and rejects the rest, and after resolving the key by `kid` it confirms the key's type matches that algorithm rather than trusting the token's declaration.

saying these in an interview costs you the question

  • Assumes a 256-bit EC key is weaker than 2048-bit RSA
  • Enables every algorithm the library supports
  • Treats PS256 as a drop-in with no consumer check
  • Chooses on benchmark numbers instead of consumer support
  • Believes ES512 uses a P-512 curve

context