Skip to content
ecdsa.com
jsonwebtoken / jws / jwa (Node.js)JWT libraries

Error message

TypeError: "ES256" signatures must be "64" bytes, saw "71"

Also printed as

  • "ES256" signatures must be "64" bytes, saw "70"
  • "ES256" signatures must be "64" bytes, saw "72"
  • "ES384" signatures must be "96" bytes, saw "103"
  • "ES512" signatures must be "132" bytes, saw "139"

The "saw" number varies between 70 and 72 for ES256 (the DER length depends on the leading bits of r and s); ES384 expects 96 bytes and ES512 132. The error is a plain `TypeError`, not a `JsonWebTokenError`, so `instanceof` checks for jsonwebtoken errors do not catch it.

jsonwebtoken / jws / jwa (Node.js) — TypeError from ecdsa-sig-formatter

What it means

The token's signature segment decodes to 71 bytes, but an ES256 JWS signature must be exactly 64 bytes: the raw concatenation r‖s defined in RFC 7518 §3.4. A 70–72 byte value that starts with `0x30` is the ASN.1 DER encoding of the same signature — the format OpenSSL, Java, KMS services and Node's `crypto.sign()` produce by default. The token was minted by a signer that skipped the DER-to-raw conversion; jsonwebtoken (through ecdsa-sig-formatter) rejects it before any verification.

Why it happens

How to fix it

  1. 1.

    Ask node:crypto for raw r‖s

    `dsaEncoding: "ieee-p1363"` makes Node emit the fixed-length format JWS requires. Better still, sign with a JOSE library (jsonwebtoken's `jwt.sign`, jose's `SignJWT`), which does this for you.

    js
    import { sign } from "node:crypto";
    
    const signature = sign("sha256", Buffer.from(signingInput), {
      key: privateKey,
      dsaEncoding: "ieee-p1363", // raw r||s: 64 bytes for P-256, as RFC 7518 §3.4 requires
    });
    const token = signingInput + "." + signature.toString("base64url");
  2. 2.

    Convert DER from a KMS before assembling the token

    `ecdsa-sig-formatter` (installed with jsonwebtoken through jws/jwa) converts DER to the JOSE format. The DER ⇄ raw converter shows r and s for both forms so you can confirm the conversion.

    js
    import ecdsaSigFormatter from "ecdsa-sig-formatter";
    
    // AWS KMS and Google Cloud KMS return DER; convert once before assembling the JWS.
    const derSignature = Buffer.from(kmsResponse.Signature);
    const joseSignature = ecdsaSigFormatter.derToJose(derSignature, "ES256"); // base64url, 64 bytes decoded
    const token = signingInput + "." + joseSignature;

Related errors

Browse the full signature error database