【问题标题】:How does node.bcrypt.js compare hashed and plaintext passwords without the salt?node.bcrypt.js 如何比较没有加盐的散列密码和明文密码?
【发布时间】:2012-10-12 23:12:29
【问题描述】:

来自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
});

从上面看,比较中怎么可能没有盐值?我在这里错过了什么?

【问题讨论】:

    标签: node.js bcrypt


    【解决方案1】:

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

    【讨论】:

    • 我还是不明白。在比较过程中,如果不提供盐,它如何知道哈希的哪一部分是盐?
    • bcrypt 是一个标准,总是将盐与哈希以相同的格式连接起来。您在加密时提供盐,并将其合并到哈希中。 bcrypt 将只能解密最初使用 bcrypt 加密的数据,否则,您是对的 - 它无法知道哪一部分是哈希,哪一部分是盐。
    • 好的,我们明白了:盐与哈希一起存储。 bcrypt 是开源的,所以这意味着每个人都知道它是如何存储它的。所以你知道如何提取它,或者如何从纯文本密码生成哈希。这如何帮助保护密码免受哈希彩虹表的扫描,这基本上是 salt 背后的主要思想?
    • 攻击者是否知道任何特定哈希的盐并不重要,这不是秘密。为每个密码使用不同的盐意味着攻击者无法使用通用值预先计算哈希值。每个人都使用不同的盐,他们需要为每个密码重新计算任何表,这使得它们无用。
    • 这样看,如果攻击者知道数据库中某些用户的盐分,像这样:column_password = hash, column_salt = salt vs column_password = hash_salt。攻击者仍然拥有相同的信息。重点是让每个密码都变得如此随机和更大,以至于不太可能有人预先计算过它。
    【解决方案2】:

    我也有与原始海报相同的问题,我环顾四周并尝试不同的事情来理解机制。正如其他人已经指出的那样,盐被连接到最终的哈希值。所以这意味着几件事:

    1. 算法必须知道盐的长度
    2. 还必须知道盐在最终字符串中的位置。例如如果从左侧或右侧偏移特定数字。

    这两件事通常在实现中是硬编码的,例如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');
            }
        });
    }
    

    【讨论】:

      【解决方案3】:

      因为我自己也有同样的问题,所以我很清楚你在想什么。

      您对用于Cryptographic 算法的"Secret Key" 和用于减慢加密过程并使黑客更难使用暴力破解的“Salt”有误解。

      当您使用普通密码和 salt 来生成哈希时,此哈希将密码本身用作密钥!因此,下次您将尝试将其与纯密码进行比较时,此纯密码必须与您用于生成哈希的密码完全相同!这就是为什么您不必将其存储在其他地方的原因,因为它始终由用户在注册和登录步骤中提供!

      【讨论】:

        【解决方案4】:

        盐被合并到哈希中。比较函数只是简单地从散列中提取盐,然后使用它来散列密码并执行比较。

        当用户登录我们的系统时,我们应该检查输入的密码是否正确。与其他系统会解密数据库中的密码(如果它是加密的)并将其与用户输入的密码进行比较,我对 bcrypt 所做的(假设它实现单向散列)是对输入的密码进行加密用户。为此,我将密码传递给 bcrypt 以计算散列,同时还将密码存储在与用户关联的数据库中(散列)。这是因为,如前所述,bcrypt 算法使用随机段(盐)来生成与密码关联的哈希。这个是和密码一起保存的,需要重新计算用户输入密码的hash,最后和注册时输入的密码比较,看是否匹配。

        【讨论】:

          【解决方案5】:

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

          例如:

          输入这个纯密码:

          546456546456546456456546111

          使用 Bcrypt 的上述纯文本的哈希密码:

          $2b$10$uuIKmW3Pvme9tH8qOn/H7uZqlv9ENS7zlIbkMvCSDIv7aup3WNH9W

          所以在上面的哈希密码中,有$符号分隔的三个字段。

          i) 第一部分 $2b$ 标识使用的 bcrypt 算法版本。

          ii) 第二部分 $10$ 10 是成本因素(在我们创建盐串时,只有盐轮。如果我们进行 15 轮,那么价值将是 $15$

          iii) 第三部分是前 22 个字符(只不过是盐字符串) 在这种情况下是

          uuIKmW3Pvme9tH8qOn/H7u

          剩下的字符串是散列密码。 所以基本上,saltedHash = salt string + hashedPassword 可以防止彩虹表攻击。

          【讨论】:

          • 这应该是公认的答案,因为它的简明解释
          【解决方案6】:

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

          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
          

          【讨论】:

            猜你喜欢
            • 2011-06-02
            • 2015-02-17
            • 2015-08-20
            • 2011-10-29
            • 2014-06-10
            • 1970-01-01
            • 1970-01-01
            • 2012-03-24
            相关资源
            最近更新 更多