node.bcrypt.js如何在没有盐的情况下比较散列密码和明文密码?

vhmi4jdf  于 2023-06-22  发布在  Node.js
关注(0)|答案(6)|浏览(148)

github
要散列密码,请执行以下操作:

var bcrypt = require('bcrypt');
bcrypt.genSalt(10, function(err, salt) {
    bcrypt.hash("B4c0/\/", salt, function(err, hash) {
        // Store hash in your password DB.
    });
});

要检查密码:

// 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
});

从上面来看,比较中怎么可能没有涉及盐值?我错过了什么?

tpxzln5u

tpxzln5u1#

盐被合并到散列中(作为明文)。compare函数只是从哈希中提取盐值,然后使用它来哈希密码并执行比较。

bq8i3lrv

bq8i3lrv2#

Bcrypt比较散列密码和没有盐字符串的明文密码,因为散列密码包含我们在散列时创建的盐字符串。

例如:

以这个普通密码为例:

546456546456546456546111

使用Bcrypt对上面的纯文本进行散列的密码:

$2b$10$uuIKmW3Pvme9tH8qOn/H7uZqlv9ENS7zlIbkMvCSDIV7aup3WNH9W

因此,在上面的哈希密码中,有三个由**$符号分隔的字段。
I)第一部分
$2b$标识所使用的Bcrypt算法版本。
II)第二部分
$10$10是成本因素(只有创建盐串时使用的盐轮)如果我们做15轮,那么价值将是$15$**
III)第三部分是前22个字符,是盐串。在这种情况下是的

uuIKmW3Pvme9tH8qOn/H7u

剩下的字符串是哈希密码-Zqlv 9 ENS 7zlIbkMvCSDIV 7aup 3 WNH 9 W
所以基本上,saltedHash = salt字符串+ hashedPassword来防止彩虹表攻击。

lpwwtiir

lpwwtiir3#

我也有同样的问题,作为原来的海报,它采取了看一点环顾四周,并尝试不同的东西,以了解机制。正如其他人已经指出的那样,盐被连接到最终散列。这意味着几件事:
1.算法必须知道盐的长度
1.还必须知道盐在最终字符串中的位置。例如如果从左或右偏移特定的数字。
这两个东西通常在实现中被硬编码,例如。bcryptjs的bcrypt实现源定义盐长度为16

/**
* @type {number}
* @const
* @private
*/

var BCRYPT_SALT_LEN = 16;

因此,为了说明这个想法背后的基本概念,如果有人想手动完成,它看起来类似于下面。我不建议你自己实现这样的东西,如果有库可以做的话。

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');
        }
    });
}
mitkmikd

mitkmikd4#

因为我自己也有同样的问题,我知道你在想什么。
您对Cryptographic算法中使用的"Secret Key"和用于减慢加密过程并使黑客更难使用蛮力的“Salt”之间存在误解。

  • 当您使用明文密码和salt生成哈希时,此哈希使用密码本身作为密钥!因此,下次您尝试将其与普通密码进行比较时,该普通密码必须与您用于生成哈希的密码完全相同!所以这就是为什么你不需要把它存储在其他地方,因为它总是由用户在注册和登录步骤中提供的!*
mcdcgff0

mcdcgff05#

它只是一个固定长度的字符串。

console.log("");
var salt = bcrypt.genSaltSync(10);
console.log(salt);
hash = bcrypt.hashSync("foobar", salt);
console.log(hash);

console.log("");
var salt = bcrypt.genSaltSync(10);
console.log(salt);
hash = bcrypt.hashSync("foobar", salt);
console.log(hash);

console.log("");
var salt = bcrypt.genSaltSync(10);
console.log(salt);
hash = bcrypt.hashSync("foobar", salt);
console.log(hash);
$2a$10$onmcKV.USxnoQAsQwBFB3e
$2a$10$onmcKV.USxnoQAsQwBFB3eytL3UZvZ5v/SudaWyaB9Vuq9buUqGO2

$2a$10$mwQfdyVS9dsO4SuxoR5Ime
$2a$10$mwQfdyVS9dsO4SuxoR5ImeG7atz7RXGRXb.c0VHp5zSn1N2VOA.Vq

$2a$10$uVUuJr6LryjchhKEg6PH7u
$2a$10$uVUuJr6LryjchhKEg6PH7unTw8aJGK0i3266c5kqDBLJkf80RHEpq

$2a$10$Y.upG5/54zvJyZacRxP17O
$2a$10$Y.upG5/54zvJyZacRxP17OH60BC0hQRMNfQjJxSWE77fyBrbzalmS
vngu2lb8

vngu2lb86#

盐被掺入散列中。compare函数只是从哈希中提取盐值,然后使用它来哈希密码并执行比较。
当用户登录我们的系统时,我们应该检查输入的密码是否正确。与其他系统不同的是,它会解密数据库中的密码(如果它是加密的),并将其与用户输入的密码进行比较,我对bcrypt所做的(考虑到它实现了单向散列)是加密用户输入的密码。为此,我将密码传递给bcrypt来计算hash,同时也将密码存储在与用户相关联的数据库中(hash)。这是因为,如前所述,bcrypt算法使用随机段(salt)来生成与密码相关联的散列。它与密码沿着存储,您需要它来重新计算用户输入的密码的哈希值,最后与注册时输入的密码进行比较,看看它们是否匹配。

相关问题