来自github:
哈希密码:
var bcrypt = require('bcrypt');
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash("B4c0/\/", salt, function(err, hash) {
// Store hash in your password DB.
});
});
Run Code Online (Sandbox Code Playgroud)
要检查密码:
// Load hash from your password DB.
bcrypt.compare("B4c0/\/", hash, function(err, res) {
// res == true
});
bcrypt.compare("not_bacon", hash, function(err, res) {
// res = false
});
Run Code Online (Sandbox Code Playgroud)
从上面来看,如何在比较中不涉及盐值?我在这里错过了什么?
Bil*_*ill 82
盐被合并到散列中(作为明文).compare函数只是将salt拉出哈希值,然后使用它来哈希密码并执行比较.
Ala*_*pin 24
我也和原版海报一样有同样的问题,看了一下,尝试了不同的东西来理解机制.正如其他人已经指出的那样,盐被连接到最终的哈希值.所以这意味着几件事:
这两件事通常在实现中被硬编码,例如bcryptjs的bcrypt实现源将salt长度定义为16
/**
* @type {number}
* @const
* @private
*/
var BCRYPT_SALT_LEN = 16;
Run Code Online (Sandbox Code Playgroud)
因此,为了说明想法背后的基本概念,如果想要手动完成,它将类似于下面的内容.当你有可以实现的库时,我不建议你自己实现这样的东西.
var salt_length = 16;
var salt_offset = 0;
var genSalt = function(callback)
{
var alphaNum = '0123456789abcdefghijklmnopqurstuvwxyzABCDEFGHIJKLMNOPQURSTUVWXYZ';
var salt = '';
for (var i = 0; i < salt_length; i++) {
var j = Math.floor(Math.random() * alphaNum.length);
salt += alphaNum[j];
}
callback(salt);
}
// cryptographic hash function of your choice e.g. shar2
// preferably included from an External Library (dont reinvent the wheel)
var shar2 = function(str) {
// shar2 logic here
// return hashed string;
}
var hash = function(passwordText, callback)
{
var passwordHash = null;
genSalt(function(salt){
passwordHash = salt + shar2(passwordText + salt);
});
callback(null, passwordHash);
}
var compare = function(passwordText, passwordHash, callback)
{
var salt = passwordHash.substr(salt_offset, salt_length);
validatedHash = salt + shar2(passwordText + salt);
callback(passwordHash === validatedHash);
}
// sample usage
var encryptPassword = function(user)
{
// user is an object with fields like username, pass, email
hash(user.pass, function(err, passwordHash){
// use the hashed password here
user.pass = passwordHash;
});
return user;
}
var checkPassword = function(passwordText, user)
{
// user has been returned from database with a hashed password
compare(passwordText, user.pass, function(result){
// result will be true if the two are equal
if (result){
// succeeded
console.log('Correct Password');
}
else {
// failed
console.log('Incorrect Password');
}
});
}
Run Code Online (Sandbox Code Playgroud)
小智 8
Bcrypt 比较不带盐串的散列密码和明文密码,因为散列密码包含我们在散列时创建的盐串。
例如 :
使用这个普通密码:
546456546456546456456546111
使用 Bcrypt 对上述纯文本的哈希密码:
$2b$10$uuIKmW3Pvme9tH8qOn/H7uZqlv9ENS7zlIbkMvCSDIv7aup3WNH9W
所以在上面的哈希密码中,有3个字段以$符号分隔。
i) 第一部分$2b$标识使用的 bcrypt 算法版本。
ii) 第二部分$10$ 10 是成本因素(我们创建盐串时只有盐轮。如果我们做 15 轮,那么价值将是$15$
iii) 第三部分是前22 个字符(也就是盐串)在这种情况下它是
uuIKmW3Pvme9tH8qOn/H7u
剩下的字符串是散列密码。所以基本上,saltedHash = salt string + hashedPassword 来防止彩虹表攻击。