Encrypt Online
Choose theme

Common RS256 and ES256 JWT verification failures and how to isolate each one

A failure-led guide to diagnosing JWT verification issues in RS256 and ES256 workflows without guessing at keys or claims.

Encrypt Online Editorial Team4 min readEncoding & Transport
Common RS256 and ES256 JWT verification failures and how to isolate each one guide cover

Tip

Decode a small sample first and confirm whether you are changing representation, changing structure, or actually protecting content.

“Signature invalid” is too vague to be useful. The fix is to separate verification problems into layers: object shape, algorithm family, key selection, signature math, and claim validation.

RS256 and ES256 fail for different reasons often enough that putting them in one bucket slows down debugging. The goal here is not a giant checklist. It is a short path to the exact layer that broke.

Summary

Definition: RS256 uses RSA signatures with SHA-256, while ES256 uses ECDSA on the P-256 curve with SHA-256.

Why it matters: You cannot verify across algorithm families, and format expectations differ between RSA and EC key material.

Pitfall: A token can have a perfectly valid signature and still fail overall validation because the wrong key, issuer, audience, or time window was used.

Separate signature checks from claim checks

The first mistake is treating every verifier error as a signature problem. Some libraries bundle signature verification and claim validation into one call. That means an expired token or wrong audience may be reported in language that sounds cryptographic. Inspect the header and claims before you assume the key is bad.

When the problem really is the signature layer, start by confirming the algorithm family. An ES256 token does not become verifiable with the right RSA key, and an RS256 token does not become valid because you found some PEM that parses.

RS256 and ES256 have different failure signatures

With RS256, common failures include the wrong public key, a PEM wrapper that contains a certificate instead of the expected key structure, or a stale JWKS entry. With ES256, failures often involve curve mismatch, coordinate parsing issues, or libraries expecting a specific DER representation of the signature.

That distinction matters because ES256 bugs are frequently serialization bugs. The key may be correct, but the library expects the signature or key to be represented differently. RS256 problems, by contrast, are more often key-selection or issuer-rotation problems.

  • RS256: stale key, wrong PEM type, wrong issuer, wrong kid.
  • ES256: wrong curve, wrong key format, signature-encoding mismatch, mismatched JOSE algorithm assumptions.

Use a fixed isolation order

Read the header. Confirm alg. Read the claims and note iss, aud, exp, nbf. Select the key by kid if present. Confirm the key type matches the algorithm family. Only then run verification. This order is intentionally boring. Boring is good. It stops the same three variables from moving at once.

Once you can say which layer failed, the repair gets smaller. That is the real objective: reduce the problem until the next action is obvious.

Quick example

Use this when you want a minimal “am I even in the right algorithm family?” check.

What to notice: The header says EC-based verification. A PEM or JWK that represents RSA is wrong before you compute anything.

JSON
{
  "alg": "ES256",
  "kid": "mobile-login-01",
  "iss": "https://issuer.example",
  "aud": "api://client-app"
}

Practical check

  • Write down alg, kid, iss, aud, and the expected public-key family.
  • Treat “expired” and “wrong audience” as claim failures, not signature failures.
  • If EC verification fails, inspect curve and serialization before replacing the key blindly.

FAQ

Can I just switch the header from ES256 to RS256 and retry?

No. The header participates in the signed content, so that change creates a different object and invalidates the original signature.

Does decoding prove the key is correct?

No. It only proves the token is structurally readable.

Developer workflow

Use this guide as a representation check before you move bytes between an API, token, URL, or file format.

  1. Encode or decode a small sample first, not the production payload.
  2. Confirm whether the step changes only representation or changes the underlying structure.
  3. Keep the original and transformed values together until the receiving system accepts the result.
Text
1. raw bytes or text
2. encode/decode for transport
3. decode back to confirm round trip
4. send only after structure still matches

References