【发布时间】:2014-12-18 14:04:26
【问题描述】:
我正在寻找一种使用 Node.js 存储用户密码的简单、安全的解决方案。我是密码学新手,但一直试图通过在线研究拼凑出一个解决方案。我正在寻找验证,我想出的是一个可靠的解决方案,适用于具有基本(而不是银行、医院等)安全需求的 Web 应用程序。这里是:
var crypto = require('crypto');
var SALT_LENGTH = 64;
var KEY_LENGTH = 64;
var ITERATIONS = 1000;
function createHashedPassword(plainTextPassword, cb) {
crypto.randomBytes(SALT_LENGTH, function (err, salt) {
console.time('password-hash');
crypto.pbkdf2(plainTextPassword, salt, ITERATIONS, KEY_LENGTH, function (err, derivedKey) {
console.timeEnd('password-hash');
return cb(null, {derivedKey: derivedKey, salt: salt, iterations: ITERATIONS});
});
});
};
...以下是我做出的选择让我走到了这一步:
使用什么哈希算法?
基于this widely referenced article,看起来领先的竞争者是 PBKDF2、bcrypt 和 scrypt。我选择了 PBKDF2,因为它在 Node 中内置了支持。
要使用什么大小的盐?
This stack overflow answer 似乎是我能找到的最直接的答案。我仍然不太清楚为什么 64 字节是正确的盐大小。当我四处搜索时,我得到了其他堆栈交换答案,例如this,但我不确定它是否适用于 Node 算法?在这里完全混淆了,针对使用此节点功能的新手的解释会很棒。
使用什么密钥长度?
再一次,我的选择主要基于the same answer as above,但我对“为什么”的基本知识同样模糊不清。答案是“生成小于输入的密钥是一种浪费,因此至少使用 64 个字节”。嗯?再一次,一个实用的解释会很有帮助。
要使用多少次迭代?
对于这个问题,我的选择基于this stack exchange answer。我不太了解,但我确实知道该算法应该花费大约 8 毫秒。因此,如您所见,我在函数上设置了计时器,并调整了迭代以使其在我的机器上处于该范围内。
谢谢!
【问题讨论】:
-
在安全性方面,通常最好坚持使用知名且经过良好测试的库。我想到了 Passport.JS,它有一些插件可以用来处理散列。
-
感谢@Pier-LucGendreau。我正在使用 PassportJS,但它不包含用于散列和存储密码的代码作为其库的一部分,或者它的子模块。如果我遗漏了什么,请告诉我。
-
好的,我看了一下……但是,我看到上面提到的常量有更多看似随意的选择。他们选择 32 字节的默认 salt 长度、512 字节的密钥长度和 25000 次迭代。在我对以下答案的评论中:'credential' 节点包,创建者说“salt 的大小应该与哈希。不再更短,也不再“。这些实现之一是不正确的!这展示了我在研究过程中所看到的......我发现的每个实现都对这些常量使用不同的值,但没有解释为什么。
-
最重要的是,请记住,没有解决方案是防弹的。当今暴力破解的最佳解决方案是慢散列! 20 年前,您可以轻松地依赖 DES 或 RSA,而今天这些都不是安全的。它通过第三方验证层层叠加,即使那样你也只是挥手....
标签: node.js cryptography passwords salt pbkdf2