Node 中密码存储的密码学最佳实践
Posted
技术标签:
【中文标题】Node 中密码存储的密码学最佳实践【英文标题】:Cryptography best practices for password storage in Node 【发布时间】: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,但它不包含用于散列和存储密码的代码作为其库的一部分,或者它的子模块。如果我遗漏了什么,请告诉我。 你可以使用github.com/saintedlama/passport-local-mongoose 好的,我看了一下……但是,我看到上面提到的常量有更多看似随意的选择。他们选择 32 字节的默认 salt 长度、512 字节的密钥长度和 25000 次迭代。在我对以下答案的评论中:'credential' 节点包,创建者说“salt 的大小应该与哈希。不再更短,也不再“。这些实现之一是不正确的!这展示了我在研究过程中所看到的......我发现的每个实现都对这些常量使用不同的值,但没有解释为什么。 最重要的是,请记住,没有解决方案是防弹的。当今暴力破解的最佳解决方案是慢散列! 20 年前,您可以轻松地依赖 DES 或 RSA,而今天这些都不是安全的。它通过第三方验证层层叠加,即使那样你也只是挥手.... 【参考方案1】:NPM 包credential 处理所有这些
你可以在Programming javascript Applications这本书里看到作者的写法
【讨论】:
我查看了这些链接,“凭据”包似乎在做与我上面相同类型的事情。在他的源代码中,他使用 66 字节的盐长度和密钥长度,以及 1000 次迭代的默认值。在包的自述文件中,他说“盐应该和散列一样大小。不再更短,也不再”。这些都是很好的信息,但我希望至少能看到“为什么”的基本解释? @markdb314 security.stackexchange.com 可能会更好地解释“为什么” 是的,我可能会在那里发帖......但答案通常比我能理解的更详细。我只是想找人自信地告诉我要使用哪些常量,以及一个简单的“为什么”。【参考方案2】:我强烈推荐使用 BCrypt。该算法有很多优点,大多数实现都会为您处理所有这些问题。
如this answer中所述:
Bcrypt 拥有加密算法所能达到的最佳声誉:它已经存在了相当长的一段时间,被广泛使用,“引起了人们的关注”,但至今仍未被打破。
我在这里写了一篇关于如何在 node/express 以及其他框架中实现 BCrypt 的详细文章:http://davismj.me/blog/bcrypt
【讨论】:
以上是关于Node 中密码存储的密码学最佳实践的主要内容,如果未能解决你的问题,请参考以下文章