NodeJS实现HKDFExpand与Python版本结果不一致问题求助
Node.js crypto实现HKDFExpand与Python版本结果不一致问题
我尝试在NodeJS中使用crypto库实现HKDFExpand,目标是解密Bitwarden(密码管理器)的加密密码保护导出文件。复刻Python版本的行为时,生成的扩展密钥结果和Python版本不一样。
原代码对比
Javascript代码
import crypto from 'crypto' const salt = 'salt' const iterations = 100000 const password = '123' const masterKey = crypto.pbkdf2Sync(password, salt, iterations, 32,'sha256'); const streched = crypto.createHmac('sha256', 'enc').update(masterKey).digest(); console.log(masterKey.toString('hex')) // 5bb4...5990 <- 结果一致 console.log(streched.toString('hex')) // 82be...6890 <- 结果不同
Python代码
from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC from cryptography.hazmat.primitives.kdf.hkdf import HKDFExpand salt = 'salt' iterations = 100000 password = b'123' kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=bytes(salt, "utf-8"), iterations=iterations,backend=default_backend()) master_key = kdf.derive(password) hkdf = HKDFExpand(algorithm=hashes.SHA256(), length=32, info=b"enc", backend=default_backend()) streched = hkdf.derive(master_key) print(master_key.hex()) # 5bb4...5990 <- 结果一致 print(streched.hex()) # 5bf9...473b <- 结果不同
问题原因
你的Node.js代码完全搞反了HKDF扩展步骤的参数,并且缺少了HKDF规范要求的后缀字节:
- HKDFExpand的核心是用主密钥(masterKey)作为HMAC的密钥,而不是把"enc"作为密钥
- 标准HKDF扩展步骤中,每一轮的输入需要拼接一个单字节的计数器(第一轮是
0x01),Python的HKDFExpand会自动处理这个逻辑
修正后的Node.js代码
import crypto from 'crypto' const salt = 'salt' const iterations = 100000 const password = '123' const masterKey = crypto.pbkdf2Sync(password, salt, iterations, 32,'sha256'); // 构造HKDFExpand的输入:info字符串 + 计数器字节0x01 const infoBuffer = Buffer.from('enc', 'utf8'); const hmacInput = Buffer.concat([infoBuffer, Buffer.from([0x01])]); // 用masterKey作为HMAC密钥,更新构造好的输入 const streched = crypto.createHmac('sha256', masterKey).update(hmacInput).digest(); console.log(masterKey.toString('hex')) // 和Python结果一致 console.log(streched.toString('hex')) // 现在和Python的5bf9...473b完全匹配
验证说明
修正后的代码严格遵循HKDF扩展步骤的规范:
- PRK(伪随机密钥)就是PBKDF2生成的masterKey
- 生成T(1) = HMAC-SHA256(PRK, "enc" || 0x01)
- 取T(1)的前32字节(正好是SHA256的输出长度)作为最终扩展密钥,和Python的
HKDFExpand行为完全一致
内容的提问来源于stack exchange,提问作者anonymous
相关产品推荐
相关产品推荐

