在Python 2.7中使用bcrypt
,我可以看到该示例使用bcrypt.hashpw
对存储密码进行哈希处理,并验证给定的密码是否与哈希值相匹配,如下所示:
import bcrypt
password = b"somepassword"
hashed = bcrypt.hashpw(password, bcrypt.gensalt())
好的,到目前为止一切顺利。现在使用bcrypt对给定的密码进行哈希处理,因此它是一个哈希字节字符串。
现在,这里让我感到困惑的部分是:要检查明文密码是否与哈希密码匹配,使用相同的函数,使用哈希密码作为salt:
if bcrypt.hashpw(password, hashed) == hashed:
print("It Matches!")
else:
print("It Does not Match :(")
两个bcrypt.hashpw
调用的结果是否不同,因为输入盐是不同的?
我能想到的唯一合理的答案是,在将前缀添加到哈希密码之前,盐被截断为固定长度。这样,当使用散列的结果时,仅留下生成的盐(在剥离尾随的散列密码之后),并且使用截断的盐散列密码的结果与原始密码相同。但是,我没有任何证据支持这一点。
为什么这样做?
答案 0 :(得分:8)
在表达式bcrypt.hashpw(password, hashed)
中,只有hashed
的前几个字符用于salt,而不是整个字符串。
例如,在此示例中,hashpw()
的输出如何以salt开头:
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个字符。
答案 1 :(得分:5)
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
,从而产生与原始相同的salt-hash-pair相同pw
输入的密码。