【问题标题】:Why can bcrypt.hashpw be used both for hashing and verifying passwords?为什么 bcrypt.hashpw 可以同时用于哈希和验证密码?
【发布时间】:2015-02-09 08:52:53
【问题描述】:

在 Python 2.7 中使用bcrypt,我可以看到该示例使用bcrypt.hashpw 对密码进行哈希存储并验证给定密码是否与哈希密码匹配,如下所示:

散列

import bcrypt
password = b"somepassword"
hashed = bcrypt.hashpw(password, bcrypt.gensalt())

好的,到目前为止一切顺利。给定的密​​码现在使用 bcrypt 进行哈希处理,因此它是一串哈希字节。


验证

现在,让我感到困惑的部分是:为了检查明文密码是否与散列密码匹配,使用了 same 函数,将散列密码用作盐:

if bcrypt.hashpw(password, hashed) == hashed:
    print("It Matches!")
else:
    print("It Does not Match :(")


发生了什么?

由于输入盐不同,两个bcrypt.hashpw 调用的结果不应该不同吗?

我能想到的唯一合理的答案是盐在被添加到散列密码之前被截断为固定长度。这样,当使用散列的结果时,只剩下生成的盐(在剥去尾随的散列密码之后),并且用截断的盐散列密码的结果与原始相同。不过,我没有任何证据支持这一点。

为什么会这样?

【问题讨论】:

    标签: python hash salt bcrypt


    【解决方案1】:

    在表达式bcrypt.hashpw(password, hashed) 中,只有hashed 的前几个字符用于salt,而不是整个字符串。

    例如,在此示例中,hashpw() 的输出如何以盐开头:

    salt1 = b"$2a$12$w40nlebw3XyoZ5Cqke14M."
    
    print "salt1:", salt1
    print "hash1:", bcrypt.hashpw(password, salt1)
    

    打印:

    salt1: $2a$12$w40nlebw3XyoZ5Cqke14M.
    hash1: $2a$12$w40nlebw3XyoZ5Cqke14M.d.7cdO2wJhr/K6ZSDjODIxLrPmYzY/a
    

    所以有一个约定,盐只上升第一个句点或前 29 个字符。

    【讨论】:

      【解决方案2】:

      hashpw 函数返回加盐哈希(迭代多次,遵循 bcyrpt 规范),前面是使用的盐(并以点作为分隔符)。

      In : salt = bcrypt.gensalt()
      In : all(salt == bcrypt.hashpw(pw,salt)[:len(salt)] for pw in ('','12345','asdfgh'))
      Out: True
      

      如果bcrypt.hashpw 的第二个参数被识别为VALID_SALT.VALID_HASH 的形式,那么salt 会自动设置为VALID_SALT,从而在相同的pw 上生成与原始密码相同的salt-hash-pair输入。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-06-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-11
        • 1970-01-01
        • 2016-04-19
        • 1970-01-01
        相关资源
        最近更新 更多