flashman
← All posts

JWT ECDSA DER and JOSE signature debugging

Debug ES256 JWT signatures by separating DER from JOSE encoding, checking fixed-width integers, preserving signing bytes, and validating curves and keys safely.

2026-09-13 · 6 min read · Rahul Chitturi

  • jwt
  • ecdsa
  • cryptography

ECDSA libraries often return an ASN.1 DER sequence containing two signed integers, while JWS represents the same r and s values as one fixed-width raw byte string. Copying a DER signature directly into an ES256 JWT produces a token that can look well formed yet fail verification everywhere.

For ES256, the JOSE signature is exactly 64 bytes before Base64url encoding: 32 bytes for r followed by 32 bytes for s.

Separate cryptographic values from encodings

Decode a public test signature and record whether the producer emits DER or fixed-width JOSE form. DER integers may contain a leading zero to keep them positive; JOSE removes that sign padding and left-pads each unsigned value to the curve width.

  • Require the exact signature length for the selected algorithm.
  • Reject negative, zero, oversized, or malformed integers.
  • Do not confuse ES256 with a 256-byte signature.
  • Keep Base64url padding policy consistent with JWS.

Verify the original signing input

ECDSA verifies the ASCII protected-header segment, a period, and the payload segment exactly as transmitted. Parsing and reserializing either JSON object changes those bytes even when the decoded claims appear equal.

Constrain the algorithm and curve from trusted issuer policy. Never select an arbitrary key or algorithm solely because the token header requests it.

Use synthetic conformance vectors

Use JWT and Base64 tools to inspect disposable segments, hash to label exact public inputs, and diff to compare byte-rendered signatures. Perform actual verification in a maintained JOSE library.

Test required leading zeros, high-bit integers, wrong lengths, DER passed as JOSE, altered segments, wrong curves, malformed keys, algorithm rejection, key rotation, and cross-language producer-verifier pairs.

Try these tools