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
Os parâmetros de geração da chave reaproveitados em sign/verify
comumGuardar uma única constante `ALG = { name: "ECDSA", namedCurve: "P-256" }` e passá-la para tudo funciona com `generateKey` e `importKey`, mas `sign` precisa de `hash`.
Nome do hash escrito no estilo do JOSE ou do OpenSSL
comumOs nomes no WebCrypto são `SHA-256`, `SHA-384`, `SHA-512` (com hífen). `SHA256`, `sha256` sem hífen ou `ES256` não são reconhecidos.
Esperar que a chave traga o hash
ocasionalCódigo portado do RSA (chaves `RSASSA-PKCS1-v1_5` têm `hash` nos parâmetros de importação) supõe que as chaves ECDSA também tenham; elas não têm.
Como corrigir
- 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);