crypto.subtle.generatekey生成aes等对称密钥时,首参须为字符串(如"aes-gcm"),且必须显式指定extractable和usages;usages需匹配操作(如["encrypt","decrypt"]),密钥长度须与算法一致(如aes-256对应length: 256),extractable: true才可导出密钥。

crypto.subtle.generateKey 生成对称密钥(如 AES)
生成对称密钥时,generateKey 的第一个参数必须是字符串或对象(如 "AES-GCM"),且 extractable 和 usages 必须显式指定——漏掉任一字段会直接抛错 TypeError: Cannot create a key with no usages。
常见错误是把 usages 写成 ["encrypt", "decrypt"] 却忘了密钥长度匹配算法要求:AES-128 要 length: 128,AES-256 则必须 length: 256,传 256 却用 "AES-128-GCM" 会失败。
-
extractable设为true才能用subtle.exportKey()拿到原始字节;设false(默认)则密钥只能在 SubtleCrypto 内部使用 -
usages必须严格匹配后续操作:比如只写["encrypt"],之后调decrypt()就报OperationError - AES 密钥不支持
namedCurve或modulusLength,这些是给非对称算法用的,混用会静默失败或抛DataError
const aesKey = await crypto.subtle.generateKey("AES-GCM", true, ["encrypt", "decrypt"]);
// ✅ 正确:算法名字符串 + extractable + 完整 usages
crypto.subtle.generateKey 生成非对称密钥对(如 RSA、ECDSA)
RSA 和 ECDSA 的调用结构完全不同:它们必须传入一个对象参数,含 name、modulusLength(RSA)或 namedCurve(ECC),且 usages 要分别指定给 publicKey 和 privateKey——很多人只写一个 usages 数组,结果 publicKey 没法 verify,privateKey 不能 sign。
RSA 最小 modulusLength 是 2048,设 1024 会抛 OperationError;ECC 的 namedCurve 只接受标准值如 "P-256"、"P-384",写 "secp256r1" 或大小写错误(如 "p-256")全都不行。
- RSA 密钥对中,
publicKey.usages通常为["verify"],privateKey.usages为["sign"];加密场景则反过来用["encrypt"]/["decrypt"] - ECC 不支持
modulusLength,传了会忽略或报错;RSA 不支持namedCurve,写了就失效 -
extractable只控制privateKey是否可导出;publicKey总是可导出的(只要extractable: true)
const rsaKeys = await crypto.subtle.generateKey(
{ name: "RSA-OAEP", modulusLength: 2048, publicExponent: new Uint8Array([1, 0, 1]), hash: "SHA-256" },
true,
{ publicKey: ["encrypt"], privateKey: ["decrypt"] }
);
为什么 generateKey 返回的是 Promise 或 Promise
返回类型取决于算法:对称算法(AES、HMAC)返回 Promise<cryptokey></cryptokey>,因为只生成单个密钥;非对称算法(RSA、ECDSA、Ed25519)返回 Promise<cryptokeypair></cryptokeypair>,包含 publicKey 和 privateKey 两个属性。混淆这两者会导致解构错误,比如对 AES 结果写 const { publicKey } = await generateKey(...),结果 publicKey 是 undefined。
另一个坑是没等 Promise settle 就直接传给 encrypt() 或 sign()——这些 API 不接受 Promise,只认 CryptoKey 实例,必须用 await 或 .then() 解包。
- 判断类型可用
key instanceof CryptoKey(对称)或keyPair instanceof CryptoKeyPair(非对称) - ECDSA 和 Ed25519 的
usages不支持["encrypt"]或["decrypt"],只允许签名/验签相关操作 - 浏览器兼容性要注意:
"Ed25519"在 Safari 16.4+ 才支持,旧版会抛NotSupportedError
导出密钥时 exportKey 报错 “InvalidAccessError”
这个错误几乎都源于密钥创建时 extractable 设成了 false(或没传,默认 false)。一旦密钥不可提取,后续任何 exportKey("jwk")、exportKey("raw") 都会立刻失败,且无法补救——密钥对象本身不可变。
还有种情况是导出格式和密钥类型不匹配:比如用 "spki" 格式导出 AES 密钥(只支持 RSA/EC 公钥),或用 "pkcs8" 导出公钥(它只用于私钥)。这些都会触发 DataError,而不是 InvalidAccessError,但初学者容易混淆。
- 对称密钥只能用
"raw"或"jwk"导出;"spki"和"pkcs8"仅限非对称密钥 - ECDSA 公钥用
"spki",私钥用"pkcs8";RSA 两者都支持,但格式内容不同 - 导出 JWK 时,
extractable: false的密钥仍可导出,但k字段为null(对称)或缺失d(私钥)
最稳妥的做法:生成时就明确设 extractable: true,除非你确定密钥永远只在 SubtleCrypto 内部流转。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











