Jak node.bcrypt.js porównuje hashowane i zwykłe hasła bez soli?

From github :

Aby hashować hasło:

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

Aby sprawdzić hasło:

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

Z góry, jak nie ma wartości soli w porównaniach? Co mi umyka?

Author: AJ., 2012-10-23

2 answers

Sól jest włączona do hash (jako zwykły tekst). Funkcja porównywania po prostu wyciąga sól z hasha, a następnie wykorzystuje ją do hashowania hasła i przeprowadzania porównania.

 56
Author: Bill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-23 06:00:12

Też miałem to samo pytanie co oryginalny plakat i trochę się rozglądałem i próbowałem różnych rzeczy, aby zrozumieć mechanizm. Jak już zauważyli inni, sól jest łączona z końcowym Haszem. Więc to oznacza kilka rzeczy:

  1. algorytm musi znać długość soli
  2. musi również znać pozycję soli w końcowym łańcuchu. np. w przypadku przesunięcia o określoną liczbę z lewej lub prawej strony.

Te dwa zwykle w implementacji rzeczy są zakodowane na twardo, np. źródło implementacji bcrypt dla bcryptjs definiuje długość soli jako 16

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

var BCRYPT_SALT_LEN = 16;

Aby zilustrować podstawową koncepcję stojącą za tym pomysłem, gdyby ktoś chciał zrobić to ręcznie, wyglądałby podobnie do poniższego. Nie polecam implementowania takich rzeczy samemu, gdy są biblioteki, które możesz zrobić.

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');
        }
    });
}
 18
Author: Alappin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-05 08:27:33