如何导入ECDH密钥用于Subtle Crypto的密钥派生?
解决Subtle Crypto导入ECDH密钥用于派生的错误问题
错误原因分析
你遇到的问题有两个核心原因:
- 密钥格式不合法:
getRandomValues生成的64字节数组不是P-256曲线的合法ECDH密钥——P-256的私钥固定为32字节,未压缩公钥是65字节,压缩公钥是33字节,你生成的长度完全不符合规范。 - 密钥类型与用法不匹配:导入ECDH密钥时必须明确指定是公钥还是私钥(通过
public参数),且公钥不具备deriveKey权限——只有私钥才能用于ECDH密钥派生,公钥仅作为配对方的参数参与派生流程。
正确的导入步骤
1. 导入ECDH私钥用于派生
如果你要导入的是私钥,需确保私钥是32字节的合法P-256私钥(比如从generateKey生成后导出的密钥),导入时指定public: false,用法设置为["deriveKey"]:
// 先生成合法密钥对并导出私钥(模拟你已有的合法私钥) const keyPair = await window.crypto.subtle.generateKey( { name: "ECDH", namedCurve: "P-256" }, true, ["deriveKey"] ); const exportedPrivateKey = await window.crypto.subtle.exportKey("raw", keyPair.privateKey); // 导入私钥用于派生 const importedPrivateKey = await window.crypto.subtle.importKey( "raw", exportedPrivateKey, { name: "ECDH", namedCurve: "P-256", public: false }, false, ["deriveKey"] ); // 使用导入的私钥派生密钥(需传入对方的公钥) const derivedKey = await window.crypto.subtle.deriveKey( { name: "ECDH", public: otherPartyPublicKey }, importedPrivateKey, { name: "AES-GCM", length: 256 }, true, ["encrypt", "decrypt"] );
2. 导入ECDH公钥
如果你要导入的是公钥,需确保公钥是65字节(未压缩)或33字节(压缩)的合法P-256公钥,导入时指定public: true,公钥不需要deriveKey权限,用法可设为空数组:
// 导出公钥(模拟你已有的合法公钥) const exportedPublicKey = await window.crypto.subtle.exportKey("raw", keyPair.publicKey); // 导入公钥 const importedPublicKey = await window.crypto.subtle.importKey( "raw", exportedPublicKey, { name: "ECDH", namedCurve: "P-256", public: true }, false, [] );
关键注意事项
- 禁止用随机生成的任意字节数组作为ECDH密钥,必须是符合椭圆曲线规范的密钥(通常从
generateKey生成后导出,或从可信来源获取)。 - ECDH的密钥派生逻辑是:用自身私钥搭配对方公钥完成派生,公钥仅作为配对参数,不具备主动派生的权限。
内容的提问来源于stack exchange,提问作者Chris Priest
相关产品推荐
相关产品推荐

