如何用浏览器Web Crypto API的PBKDF2获得与SJCL/CyberChef一致结果?
在Firefox的Web Crypto API中实现与sjcl/CyberChef一致的PBKDF2密钥派生
要让Web Crypto API的PBKDF2结果和sjcl 1.0.8、CyberChef完全匹配,核心是严格对齐所有参数和编码方式,以下是具体实现步骤和代码:
关键参数对应
先明确三方一致的参数:
- 输入密码:
test(UTF-8编码) - 盐值:
test(UTF-8编码) - 迭代次数:10000
- 派生密钥长度:256位(32字节)
- 哈希算法:SHA-256
完整实现代码
async function derivePBKDF2Key() { // 1. 将密码和盐转换为Web Crypto需要的ArrayBuffer(UTF-8编码) const encoder = new TextEncoder(); const password = encoder.encode('test'); const salt = encoder.encode('test'); // 2. 导入密码为CryptoKey对象 const cryptoKey = await crypto.subtle.importKey( 'raw', // 密码的格式:原始二进制 password, { name: 'PBKDF2' }, // 指定算法为PBKDF2 false, // 是否允许导出密钥(这里不需要,设为false) ['deriveBits'] // 允许的操作:派生比特数据 ); // 3. 使用PBKDF2派生密钥数据 const derivedBits = await crypto.subtle.deriveBits( { name: 'PBKDF2', salt: salt, iterations: 10000, hash: 'SHA-256' // Web Crypto的哈希算法名称带连字符,注意格式 }, cryptoKey, 256 // 派生的密钥长度(单位:位) ); // 4. 将ArrayBuffer转换为十六进制字符串(匹配sjcl和CyberChef的输出格式) const hexString = Array.from(new Uint8Array(derivedBits)) .map(byte => byte.toString(16).padStart(2, '0')) .join(''); console.log(hexString); // 输出:1dee9f26ad603dc9260a3071242ef1a46270a975aff83c2178ff88974756d83b } // 执行派生 derivePBKDF2Key();
注意事项
- 编码一致性:必须使用UTF-8编码将字符串转二进制,sjcl和CyberChef默认都是UTF-8,不要用ASCII或其他编码。
- 哈希算法名称:Web Crypto中SHA-256的名称是
'SHA-256'(带连字符),写成'SHA256'会导致算法不匹配。 - 密钥长度单位:
deriveBits的第三个参数是位,256位对应32字节,和sjcl的256参数完全对应。 - 迭代次数:必须严格设置为10000,迭代次数不同会直接导致结果差异。
内容的提问来源于stack exchange,提问作者Patatetom
相关产品推荐
相关产品推荐

