2013-10-12 91 views
0

我使用下面的函數來散列用戶的密碼,下面快速的例子進行身份驗證:如何在mongoDB中存儲crypto pbkdf2?

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。這將儲存在陌生的路上散,造成這樣的內容肆虐我蒙戈主機上肆虐:

screenshot of hash in mongodb

我的問題是,有沒有存儲這些hash更好/更聰明的方法我數據庫?我試着用.toString('hex')對它進行編碼,我也嘗試將用戶架構中的hash類型更改爲buffer,但這兩種方法在嘗試登錄用戶時都使所有比較都爲false。在我的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.'); 
    }); 
} 
+0

你如何執行實際的比較?你可以展示這些代碼嗎? – robertklep

+0

@robertklep編輯添加'authenticate'功能,做比較 – Jakemmarsh

回答

1

存儲在數據庫中的十六進制字符串工作好,我的哈希值(存儲他們的「原始」在任何一個StringBuffer屬性不):

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.pbkdf2crypto.randomBytes都有同步同行)

+0

這工作。當我嘗試這之前,我不能在嘗試登錄用戶時調用'toString('hex')'。另外,我知道他們有同步對應,我在應用程序的另一部分使用它們。謝謝! – Jakemmarsh