Saltar al contenido
ecdsa.com
WebCrypto SubtleCrypto.sign / verify with ECDSAWebCrypto

Mensaje de error

TypeError: Failed to execute 'sign' on 'SubtleCrypto': EcdsaParams: hash: Missing or not an AlgorithmIdentifier

También se muestra como

  • TypeError: Failed to execute 'verify' on 'SubtleCrypto': EcdsaParams: hash: Missing or not an AlgorithmIdentifier
  • TypeError: Member EcdsaParams.hash is required and must be an instance of (object or DOMString)
  • NotSupportedError: Failed to execute 'sign' on 'SubtleCrypto': EcdsaParams: hash: Algorithm: Unrecognized name

Arriba está el texto de Chromium (con `verify` cambia el nombre del método); Safari/WebKit: «Member EcdsaParams.hash is required and must be an instance of (object or DOMString)»; Firefox notifica un `SyntaxError` genérico («An invalid or illegal string was specified»).

WebCrypto SubtleCrypto.sign / verify with ECDSA — algorithm parameter without hash (Chromium / WebKit)

Qué significa

En WebCrypto, ECDSA recibe la función hash en cada operación, no en la clave: `sign` y `verify` necesitan `{ name: "ECDSA", hash: "SHA-256" }`. La llamada pasó un objeto de algoritmo sin `hash` —normalmente el objeto `{ name, namedCurve }` de la generación de la clave—, así que el navegador rechazó los parámetros antes de firmar. (Con las claves RSA ocurre lo contrario: su hash se fija al importarlas). Un hash mal escrito, como `"SHA256"`, falla en cambio con un `NotSupportedError` sobre un nombre no reconocido.

Por qué ocurre

Cómo solucionarlo

  1. 1.

    Mantener separados los parámetros de la clave y los de la operación

    Define un objeto para crear la clave y otro para firmar. Para JWT ES256/ES384/ES512, usa SHA-256/384/512 con P-256/384/521, respectivamente.

    js
    const KEY_ALG = { name: "ECDSA", namedCurve: "P-256" };   // generateKey / importKey
    const SIGN_ALG = { name: "ECDSA", hash: "SHA-256" };        // sign / verify (ES256)
    
    const pair = await crypto.subtle.generateKey(KEY_ALG, false, ["sign", "verify"]);
    const signature = await crypto.subtle.sign(SIGN_ALG, pair.privateKey, data);   // 64 bytes, raw r||s
    const ok = await crypto.subtle.verify(SIGN_ALG, pair.publicKey, signature, data);

Errores relacionados

Explorar toda la base de datos de errores de firma