How does node.bcrypt.js compare hashed and plaintext passwords without the salt?

前端 未结 6 1949
刺人心
刺人心 2020-12-07 19:45

From github:

To hash a password:

var bcrypt = require(\'bcrypt\');
bcrypt.genSalt(10, function(err, salt) {
    bcrypt.hash(\"B4c0/\\/\", salt, funct         


        
6条回答
  •  广开言路
    2020-12-07 20:06

    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:

    1. The algorithm must know the length of the salt
    2. 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 bcryptjs defines the salt length as 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');
            }
        });
    }
    

提交回复
热议问题