Pular para o conteúdo
ecdsa.com
WebCrypto SubtleCrypto.sign / verify with ECDSAWebCrypto

Mensagem de erro

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

Também aparece 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

O texto acima é o do Chromium (com `verify`, o nome do método muda); Safari/WebKit: “Member EcdsaParams.hash is required and must be an instance of (object or DOMString)”; o Firefox informa um `SyntaxError` genérico (“An invalid or illegal string was specified”).

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

O que significa

No WebCrypto, o ECDSA recebe a função de hash por operação, não por chave: `sign` e `verify` precisam de `{ name: "ECDSA", hash: "SHA-256" }`. A chamada passou um objeto de algoritmo sem `hash` — em geral, o objeto `{ name, namedCurve }` da geração da chave —, então o navegador rejeitou os parâmetros antes de assinar. (Com chaves RSA é o contrário: o hash delas é fixado na importação.) Já um hash com nome escrito errado, como `"SHA256"`, falha com um `NotSupportedError` sobre um nome não reconhecido.

Por que acontece

Como corrigir

  1. 1.

    Manter separados os parâmetros da chave e os da operação

    Defina um objeto para a criação da chave e outro para a assinatura. Para JWT ES256/ES384/ES512, use SHA-256/384/512 com 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);

Erros relacionados

Ver toda a base de erros de assinatura