错误信息
NotSupportedError: Unrecognized algorithm name
这是 Node 的措辞;对于未知曲线,Node 还会报“Unrecognized namedCurve”。Chrome 打印“Failed to execute 'generateKey' on 'SubtleCrypto': Algorithm: Unrecognized name”,Firefox 为“Operation is not supported”,Safari 为“The operation is not supported.”——稳定不变的是 DOMException 名称 NotSupportedError。
WebCrypto crypto.subtle — browsers & Node
含义
你指定的算法(或曲线)不在这个 WebCrypto 实现提供的范围内。要么标识符有拼写错误,要么你请求的确实是标准集合之外的东西——最常见的是 secp256k1:它和 P-* 系列一样是 EC 曲线,但 WebCrypto 并不包含它。这项检查在接触任何密钥材料之前就会执行,因此名称改正后,完全相同的调用就会成功。
原因
向 WebCrypto 请求 secp256k1
常见比特币/以太坊代码常常以为 namedCurve: "secp256k1" 会像 P-256 一样可用。事实从来不是这样:WebCrypto 注册表只涵盖 P-256、P-384 和 P-521。(Node 中非 WebCrypto 的 crypto 模块确实支持 secp256k1。)
把 JWT 风格的名称当作算法名称
常见“ES256”、“RS256”或“ECDSA_P256_SHA256”是 JOSE 或其他生态系统的标识符。WebCrypto 对密钥要求 { name: "ECDSA", namedCurve: "P-256" },对操作要求 { name: "ECDSA", hash: "SHA-256" }。
在旧运行时上使用较新的算法
偶见2023~2025年间,Ed25519/X25519 陆续加入 WebCrypto;较旧的浏览器、Node 版本和部分 WebView 仍会拒绝它们。依赖它们之前,先做特性检测。
修复方法
- 1.
使用准确的 WebCrypto 标识符
名称匹配时不区分大小写,但必须是已注册的名称——而且曲线名称必须完全一致。注意这两种字典:generateKey/importKey 接受 namedCurve,而 sign/verify 接受 hash;把两者混淆是这个错误的另一种形式。
js const key = await crypto.subtle.generateKey( { name: "ECDSA", namedCurve: "P-256" }, // not "ES256", not "secp256r1" false, ["sign", "verify"], ); const sig = await crypto.subtle.sign({ name: "ECDSA", hash: "SHA-256" }, key.privateKey, data); - 2.
对于 secp256k1,改用库
在浏览器中,标准做法是使用经过审计的纯 JS 实现;在 Node 中,内置的(非 WebCrypto 的)crypto 模块原生支持这条曲线,因此服务器端代码有两种选择。
js // browser: @noble/curves (audited, dependency-free) import { secp256k1 } from "@noble/curves/secp256k1"; const ok = secp256k1.verify(signature, msgHash, publicKey); // node: built-in crypto.generateKeyPairSync("ec", { namedCurve: "secp256k1" });