错误信息
SyntaxError: Cannot create a key using the specified key usages.
也可能输出为
- SyntaxError: Usages cannot be empty when creating a key.
- SyntaxError: An invalid or illegal string was specified
- SyntaxError: A required parameter was missing or out-of-range
Chromium 为“Cannot create a key using the specified key usages.”或“Usages cannot be empty when creating a key.”;Firefox 为“An invalid or illegal string was specified”;Safari/WebKit 为“A required parameter was missing or out-of-range”。代码中应按 `e.name === "SyntaxError"` 判断。
WebCrypto SubtleCrypto.importKey / generateKey — DOMException SyntaxError (Chromium / Firefox / WebKit)
含义
`keyUsages` 数组与要创建的密钥不相符。WebCrypto 规定了每种密钥类型可以具有哪些用途:ECDSA 或 RSA 公钥只能 `verify`,私钥只能 `sign`;ECDH 公钥不接受任何用途;用空的用途列表创建私钥或对称密钥是不允许的。浏览器会在密钥产生之前,以 `SyntaxError` DOMException 拒绝这次调用。这与 `InvalidAccessError` 不同,后者出现得更晚:把已有的密钥用于它创建时并未指定的操作时才会出现。
原因
导入公钥时指定了 sign(或导入私钥时指定了 verify)
常见把同一个 `["sign", "verify"]` 数组复制到每个 `importKey` 调用中,导入单个密钥时会失败:只有 `generateKey` 会把这个列表分配给密钥对的两半。
用途列表为空
常见`generateKey(alg, true, [])`,或者用 `[]` 导入私钥。创建密钥时必须至少指定一种用途。
混淆了 ECDH 和 ECDSA
偶见用 `["sign"]` 导入 ECDH 密钥,或用 `["deriveBits"]` 导入 ECDSA 密钥,都会失败:同一个曲线点在不同算法下是不同类型的密钥。
修复方法
- 1.
按角色为每个密钥指定用途
公钥:`verify`(签名)或 `[]`(ECDH 对端公钥);私钥:`sign` 或 `deriveBits`/`deriveKey`。用途要保持最少——它们是 WebCrypto 最小权限模型的一部分。
js const alg = { name: "ECDSA", namedCurve: "P-256" }; // Public keys verify, private keys sign: const publicKey = await crypto.subtle.importKey("spki", spkiDer, alg, false, ["verify"]); const privateKey = await crypto.subtle.importKey("pkcs8", pkcs8Der, alg, false, ["sign"]); // ECDH keys derive; their public half takes no usages at all: const peer = await crypto.subtle.importKey("raw", point, { name: "ECDH", namedCurve: "P-256" }, false, []);
相关错误
InvalidAccessError: Unable to use this key to verifyWebCrypto crypto.subtle.sign / verifyDataError: Data provided to an operation does not meet requirementsWebCrypto crypto.subtle.importKeyInvalidAccessError: Failed to execute 'exportKey' on 'SubtleCrypto': key is not…WebCrypto SubtleCrypto.exportKey / wrapKey