Saltar al contenido
ecdsa.com
jsonwebtoken / jws / jwa (Node.js)Bibliotecas de JWT

Mensaje de error

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

También se muestra como

  • "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"

El número que sigue a «saw» varía entre 70 y 72 para ES256 (la longitud DER depende de los bits iniciales de r y s); ES384 espera 96 bytes y ES512, 132. El error es un `TypeError` simple, no un `JsonWebTokenError`, así que las comprobaciones `instanceof` de errores de jsonwebtoken no lo capturan.

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

Qué significa

El segmento de firma del token se decodifica en 71 bytes, pero una firma JWS ES256 debe tener exactamente 64 bytes: la concatenación en bruto r‖s definida en el RFC 7518 §3.4. Un valor de 70 a 72 bytes que empieza por `0x30` es la codificación ASN.1 DER de esa misma firma, el formato que producen por defecto OpenSSL, Java, los servicios KMS y `crypto.sign()` de Node. El token lo generó un firmante que se saltó la conversión de DER a formato en bruto; jsonwebtoken (a través de ecdsa-sig-formatter) lo rechaza antes de cualquier verificación.

Por qué ocurre

Cómo solucionarlo

  1. 1.

    Pedir a node:crypto r‖s en bruto

    `dsaEncoding: "ieee-p1363"` hace que Node emita el formato de longitud fija que exige JWS. Mejor aún, firma con una biblioteca JOSE (`jwt.sign` de jsonwebtoken, `SignJWT` de jose), que lo hace por ti.

    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.

    Convertir el DER de un KMS antes de montar el token

    `ecdsa-sig-formatter` (que se instala con jsonwebtoken a través de jws/jwa) convierte DER al formato JOSE. El conversor DER ⇄ raw muestra r y s en ambas formas para que puedas confirmar la conversión.

    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;

Errores relacionados

Explorar toda la base de datos de errores de firma