我试图弄清楚如何使用crypto模块对nodejs中的密码进行加密和散列。我可以创建哈希密码:
UserSchema.pre('save', function(next) {
var user = this;
var salt = crypto.randomBytes(128).toString('base64');
crypto.pbkdf2(user.password, salt, 10000, 512, function(err, derivedKey) {
user.password = derivedKey;
next();
});
});
但是我对如何验证密码感到困惑。
UserSchema.methods.validPassword = function(password) {
// need to salt and hash this password I think to compare
// how to I get the salt?
}
答案 0 :(得分:41)
在您使用的任何持久性机制(数据库)中,您将存储结果哈希以及盐和迭代次数,两者都是纯文本。如果每个密码使用不同的盐(您应该这样做),您还必须保存该信息。
然后,您将比较新的纯文本密码,使用相同salt(和迭代)的哈希值,然后将字节序列与存储的字节序列进行比较。
生成密码(伪)
function hashPassword(password) {
var salt = crypto.randomBytes(128).toString('base64');
var iterations = 10000;
var hash = pbkdf2(password, salt, iterations);
return {
salt: salt,
hash: hash,
iterations: iterations
};
}
验证密码(伪)
function isPasswordCorrect(savedHash, savedSalt, savedIterations, passwordAttempt) {
return savedHash == pbkdf2(passwordAttempt, savedSalt, savedIterations);
}
答案 1 :(得分:24)
基于nodejs文档(http://nodejs.org/api/crypto.html),看起来没有一种特定方法可以为您验证密码。要手动验证它,您需要计算当前提供的密码的哈希值,并将其与存储的密码进行比较以获得相等性。基本上,您将使用您对原始密码执行的质询密码执行相同的操作,但使用存储在数据库中的salt而不是生成新的密码,然后比较两个哈希值。
如果您不太愿意使用内置的加密库,我建议您改用bcrypt。这两个在安全方面大致相同,但我认为bcrypt具有更加用户友好的界面。如何使用它的一个示例(直接从上面链接的页面上的bcrypt文档中获取)将是:
创建哈希:
var bcrypt = require('bcrypt');
var salt = bcrypt.genSaltSync(10);
var hash = bcrypt.hashSync("B4c0/\/", salt);
// Store hash in your password DB.
检查密码:
// Load hash from your password DB.
bcrypt.compareSync("B4c0/\/", hash); // true
bcrypt.compareSync("not_bacon", hash); // false
编辑添加:
bcrypt的另一个优点是output of the genSalt function contains both the hash and the salt in one string。这意味着您可以只存储数据库中的单个项目,而不是两个。还提供了一种方法,可以在散列发生的同时生成盐,因此您根本不必担心管理盐。
编辑更新:
回应Peter Lyons的评论:你是100%正确的。我曾经假设我推荐的bcrypt模块是一个javascript实现,因此异步使用它不会真正加速节点的单线程模型。事实证明事实并非如此; bcrypt模块使用本机c ++代码进行计算,并且异步运行速度更快。 Peter Lyons是对的,您应该首先使用该方法的异步版本,并在必要时仅选择同步版本。异步方法可能与同步方法一样慢,但同步方法始终会很慢。
答案 2 :(得分:8)
将密码和salt存储在数据库的单独列中,或者(我的首选方法),将您的密码以与RFC 2307第5.3节兼容的格式存储在数据库中。一个例子是{X-PBKDF2}base64salt:base64digest
。您还可以将迭代计数存储在那里,这样您就可以在未来更新密码的新帐户和帐户中增加迭代次数,而不会破坏其他人的登录。
我自己PBKDF2 module for Perl的示例哈希看起来像是
{X-PBKDF2}HMACSHA1:AAAD6A:8ODUPA==:1HSdSVVwlWSZhbPGO7GIZ4iUbrk=
,其中包括使用的特定哈希算法,以及迭代次数,salt和生成的密钥。
答案 3 :(得分:6)
面对同样的问题,我将所有内容整合到一个模块中:https://www.npmjs.org/package/password-hash-and-salt
它使用pbkdf2并在单个字段中存储哈希,salt,算法和迭代。希望它有所帮助。
答案 4 :(得分:5)
我认为本教程最适合您。只是通过它,它是我发现的最好的。 Passport Tutorial with Node.js and Crypto
希望你觉得它有用。
答案 5 :(得分:1)
此方案涉及两个主要步骤
1)创建并存储密码
您必须执行以下操作。
2)验证用户密码
需要此步骤来验证用户身份。
用户将输入用户名/电子邮箱和密码。
根据输入的用户名
将salt与用户密码结合使用
使用相同的散列算法散列组合。
比较结果。
本教程详细解释了如何使用nodejs加密。正是你在寻找什么。 Salt Hash passwords using NodeJS crypto