Перейти к содержимому
ecdsa.com
WebCrypto SubtleCrypto.sign / verify with ECDSAWebCrypto

Сообщение об ошибке

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

Также выводится как

  • 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

Выше приведён текст Chromium (для `verify` меняется имя метода); Safari/WebKit: «Member EcdsaParams.hash is required and must be an instance of (object or DOMString)»; Firefox выдаёт общую ошибку `SyntaxError` («An invalid or illegal string was specified»).

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

Что это означает

В WebCrypto ECDSA получает хеш-функцию для каждой операции, а не для ключа: для `sign` и `verify` нужен `{ name: "ECDSA", hash: "SHA-256" }`. В вызов передан объект алгоритма без `hash` (обычно объект `{ name, namedCurve }`, оставшийся от генерации ключа), поэтому браузер отклонил параметры ещё до подписания. (У ключей RSA всё наоборот: их хеш фиксируется при импорте.) Хеш с опечаткой, например `"SHA256"`, вместо этого приводит к `NotSupportedError` о нераспознанном имени.

Почему это происходит

Как исправить

  1. 1.

    Разделяйте параметры ключа и параметры операции

    Заведите один объект для создания ключа и другой для подписания. Для JWT с ES256/ES384/ES512 используйте SHA-256/384/512 с P-256/384/521 соответственно.

    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);

Связанные ошибки

Открыть всю базу ошибок подписей