node.js node.bcrypt.js 如何比较没有盐的散列密码和明文密码?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13023361/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does node.bcrypt.js compare hashed and plaintext passwords without the salt?
提问by SChang
From github:
从github:
To hash a password:
要散列密码:
var bcrypt = require('bcrypt');
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash("B4c0/\/", salt, function(err, hash) {
// Store hash in your password DB.
});
});
To check a password:
要检查密码:
// 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
});
From above, how can there be no salt values involved in the comparisons? What am I missing here?
从上面,比较中怎么可能没有盐值?我在这里缺少什么?
回答by Bill
The salt is incorporated into the hash (as plaintext). The compare function simply pulls the salt out of the hash and then uses it to hash the password and perform the comparison.
盐被合并到哈希中(作为明文)。比较函数只是从散列中提取盐,然后使用它来散列密码并执行比较。
回答by Alappin
I had the same question too as the original poster and it took a look bit of looking around and trying different things to understand the mechanism. As has already been pointed out by others, the salt is concatenated to the final hash. So this means a couple of things:
我也有与原始海报相同的问题,它环顾四周并尝试不同的事情来理解机制。正如其他人已经指出的那样,盐被连接到最终的哈希值。所以这意味着几件事:
- The algorithm must know the length of the salt
- Must also know the position of the salt in the final string. e.g. if offset by a specific number from left or right.
- 算法必须知道盐的长度
- 还必须知道盐在最终字符串中的位置。例如,如果从左侧或右侧偏移特定数字。
These two things are usually hard coded in the implementation e.g. the bcrypt implementation source for bcryptjsdefines the salt length as 16
这两个东西通常在实现中硬编码,例如bcryptjs的 bcrypt 实现源将盐长度定义为 16
/**
* @type {number}
* @const
* @private
*/
var BCRYPT_SALT_LEN = 16;
So to illustrate the basic concept behind the idea if one wanted to do it manually, It would look similar to the below. I do not recommend implementing stuff like this yourself when there are libraries that you can get to do it.
所以为了说明这个想法背后的基本概念,如果你想手动完成它,它看起来类似于下面的。我不建议你自己实现这样的东西,因为有你可以做的库。
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');
}
});
}
回答by babaliaris
Because I had the same question myself, I know exactly what you are thinking about.
因为我自己也有同样的问题,所以我完全知道你在想什么。
You have a misconception between "Secret Key"which is used in Cryptographicalgorithms and "Salt" which is used to slow down the encryption process and make it harder for hackers to use brute force.
您对加密算法中使用的“秘密密钥”和用于减慢加密过程并使黑客更难使用蛮力的“盐”之间存在误解。
When you use the plain passwordand the salt to generate the hash, this hash uses as secret key the password itself! So the next time you will try to compare it with a plain password, this plain password must be the exact same one you used to generate the hash! So this is why you don't have to store it somewhere else because it is always provided by the user on both register and login steps!
当您使用普通密码和盐来生成散列时,该散列使用密码本身作为密钥!因此,下次您尝试将其与普通密码进行比较时,该普通密码必须与您用于生成哈希的密码完全相同!这就是为什么您不必将其存储在其他地方的原因,因为它始终由用户在注册和登录步骤中提供!

