跳到主要内容
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);

相关错误

浏览完整的签名错误库