如何在 mongoDB 中存储加密 pbkdf2? [英] How to store crypto pbkdf2 in mongoDB?
问题描述
我正在使用以下函数来散列用户的密码,遵循 Express 的身份验证示例:
I'm using the following function to hash a user's password, following Express's example for authentication:
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
返回.当尝试登录用户时,该函数也用于比较哈希值.
The salt
, as you can see, is returned as a string encoded in base64. The hash
, however, is returned as a SlowBuffer
. This same function is also used to compare hashes when trying to log a user in.
My Mongoose schema for Users 指定 hash
应该是 String
类型.这最终以一种奇怪的方式存储散列,导致这样的内容对我的 mongo 主机造成了严重破坏:
My Mongoose schema for Users specifies that the hash
should be of type String
. This ends up storing the hash in a strange way, resulting in contents like this which wreaked havoc on my mongo host:
我的问题是,是否有更好/更智能的方法来将此 hash
存储在我的数据库中?我尝试使用 .toString('hex')
对其进行编码,并且我还尝试将 User 架构中的 hash
类型更改为 buffer
,但是当尝试登录用户时,这两种方法都使所有比较都为假.比较是在我的 authenticate
函数中进行的,如下所示:
My question is, is there a better/smarter way to store this hash
in my database? I've tried encoding it with .toString('hex')
, and I've also tried changing the hash
type in the User schema to buffer
, but both these approaches made all comparisons false when trying to log users in. Comparisons are made in my authenticate
function, seen below:
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.');
});
}
推荐答案
将哈希作为十六进制字符串存储在数据库中对我来说工作正常(将它们原始"存储在 String
或Buffer
属性没有):
Storing the hash as a hex string in the database works okay for me (storing them 'raw' in either a String
or a Buffer
property doesn't):
var crypto = require('crypto');
var mongoose = require('mongoose');
var client = mongoose.connect('mongodb://localhost/test');
var UserSchema = new mongoose.Schema({
salt : String,
hash : String
});
var User = mongoose.model('User', UserSchema);
hash('secret', function(err, salt, key) {
new User({ salt : salt, hash : key.toString('hex') }).save(function(err, doc) {
User.findById(doc._id, function(err, doc) {
hash('secret', doc.salt, function(err, key) {
console.log('eq', doc.hash === key.toString('hex'));
});
});
});
});
(顺便说一下,crypto.pbkdf2
和 crypto.randomBytes
都有同步副本)
(by the way, both crypto.pbkdf2
and crypto.randomBytes
have synchronous counterparts)
这篇关于如何在 mongoDB 中存储加密 pbkdf2?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!