为什么bcrypt.hashpw可以同时用于散列和验证密码?

2024-05-15 06:44:07 发布

您现在位置:Python中文网/ 问答频道 /正文

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

散列

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

好吧,到目前为止还不错。给定的密码现在使用bcrypt进行散列,因此它是一个散列字节字符串。


验证

现在,让我困惑的是:要检查明文密码是否与哈希密码匹配,使用相同的函数,将哈希密码用作盐:

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


怎么了?

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

我能想到的唯一合理答案是,在将salt放在散列密码前面之前,它会被截断到一个固定的长度。这样,当使用散列结果时,只剩下生成的salt(在去掉后面的散列密码之后),使用截断的salt散列密码的结果与原始结果相同。不过,我没有任何证据支持这一点。

为什么这么做?


Tags: 函数字符串import密码示例字节itpassword
2条回答

在表达式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个字符上。

hashpw函数返回salted hash(根据bcyrpt规范多次迭代),由所用的salt进行处理(并使用点作为分隔符)。

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散列对。

相关问题 更多 >

    热门问题