密码安全不是我的强项。请帮帮我。
我使用node.js 4.2.3 express 4.13.3。我找到了一些用crypto的pbkdf2来哈希和加密密码的例子。
这是我的代码。
var salt = crypto.randomBytes(10).toString('base64');
console.log("salt > "+salt);
crypto.pbkdf2(pass, salt , 10000, 150, 'sha512',function(err, derivedKey) {
pass = derivedKey.toString('hex');
});
最终的derivedKey不包含盐。我错过了什么?我应该在保存之前手动加入两个字符串吗?
为什么有些示例使用base64
和其他hex
?要获得不同的字符串长度?什么是默认值,所以我可以使用它?
为什么不在salt和哈希密码中使用basic64
?
最终的derivedKey字符串是UTF8吗?或者这只是与它保存的数据库有关?我的数据库是UTF8。
由于
答案 0 :(得分:2)
是的,单独存储盐,未加密。确保它是随机生成的。
更重要的是,你通过要求密钥长度的150字节(每nodejs.org字节数)来削弱你的PBKDF2加密 - SHA512是一个很棒的选择,但它只提供64字节本机输出。要获得10,000个150字节输出的迭代,PBKDF2/RFC2898将执行30,000次,而离线攻击者只需要运行10,000次迭代并匹配前64个字节(如果前64个匹配,则其余将太); 你免费给了他们3:1的优势!
相反,如果你对工作因素感到满意,你应该使用30,000次64字节输出的迭代 - 你将花费相同的时间,没有区别,但攻击者现在也必须进行30,000次迭代,所以你带走了他们3:1的优势!
当您将salt传递给PBKDF2函数时,如果可以,只需传入纯二进制文件。此外,node.js文档说 - 合理地“建议盐是随机的,它们的长度大于16个字节。”这意味着二进制16字节,在base64或十六进制之前或任何转换,如果你想要的话。
您可以将salt和derivedkey保存为正确长度的BINARY以获得最有效的存储空间(然后您不必担心UTF-x与ASCII),或者您可以将一个或两个转换为BASE64或十六进制,然后根据需要转换回二进制。只要转换根据需要重新转换,Base64 vs hex vs binary就无关紧要了。
我还将迭代次数设为存储字段,因此您可以在未来几年内轻松增加它,并包含一个字段用于使用密码哈希的“版本”,因此您可以轻松更改算法未来几年如果需要的话。
答案 1 :(得分:1)
加密适用于数据,而不是字符串,这包括加密密钥。 PBKDF2生成一个数据键,可以很容易地转换为字符串,这种转换是必要的,因为许多数据字节没有相应的打印字符或unicode代码点。许多脚本语言都不能很好地处理数据,因此数据被多次转换为Base64或十六进制(十六进制)。
您可以使用Base64或十六进制作为salt和哈希密码,只需在所有用途中保持一致。
创建检查时,salt和迭代计数必须相同,您需要将它们组合或单独保存。
您的代码正在将派生密钥转换为十六进制,这很好,而base64也可以。这也是必要的,因为并非所有数据字节都是UTF-8。