【发布时间】:2013-10-13 03:59:37
【问题描述】:
按照 Express 的身份验证示例,我正在使用以下函数对用户密码进行哈希处理:
function hash(pwd, salt, fn) {
// Bytesize
var len = 128,
// Iterations. ~300ms
iterations = 12000;
if (3 == arguments.length) {
crypto.pbkdf2(pwd, salt, iterations, len, fn);
} else {
fn = salt;
crypto.randomBytes(len, function(err, salt){
if (err) return fn(err);
salt = salt.toString('base64');
crypto.pbkdf2(pwd, salt, iterations, len, function(err, hash){
if (err) return fn(err);
fn(null, salt, hash);
});
});
}
}
如您所见,salt 以 base64 编码的字符串形式返回。但是,hash 返回为SlowBuffer。在尝试登录用户时,同样的函数也用于比较哈希值。
我的用户 Mongoose 模式指定 hash 应该是 String 类型。这最终以一种奇怪的方式存储哈希,导致这样的内容对我的 mongo 主机造成了严重破坏:
我的问题是,有没有更好/更智能的方法将此hash 存储在我的数据库中?我已经尝试使用.toString('hex') 对其进行编码,并且我还尝试将用户架构中的hash 类型更改为buffer,但是这两种方法在尝试登录用户时都使所有比较错误。进行了比较在我的authenticate 函数中,如下所示:
function authenticate(name, pass, fn) {
var findUser = function(username) {
var deferred = Q.defer(),
populateObj = [
// list of paths to populate objects normally goes here
];
User.findOne({ username: name }).populate(populateObj).exec(function (err, retrievedUser) {
if (err || !retrievedUser) {
console.log(err);
deferred.reject('Cannot find user.');
}
else {
deferred.resolve(retrievedUser);
}
});
return deferred.promise;
};
findUser(name).then(function(data) {
// apply the same algorithm to the POSTed password, applying
// the hash against the pass / salt, if there is a match we
// found the user
hash(pass, data.salt, function(err, hash){
if (err) return fn(err);
if (hash == data.hash) return fn(null, data);
return fn('Invalid password.');
});
}, function() {
return fn('Failed to retrieve user.');
});
}
【问题讨论】:
-
如何进行实际比较?你能显示这些代码吗?
-
@robertklep 编辑添加
authenticate函数,用于比较