flask_bcrypt 不允许在中间带有 '\x00' 的编码字节密码

问题描述

我有一些代码接受字符串格式的密码,并在将其传递给flask_bcrypt 进行哈希处理之前使用SHA3-512 对其进行哈希处理。然而,巧合的是,我发现了一个测试用例,它产生一个哈希结果,在哈希结果中间包含 '\x00',如下所示:

password_str = 'tes15!tes15!tes15!tes15!tes15!tes15!tes15!tes15!tes15!tes15!tes15!tes15!.'
password_bytes = password_str.encode('utf-8')
hashed = hashlib.sha3_512(password_bytes).digest()

散列的结果是:

b'u~"\x98\xac\xc8E2eV\xbb\x8e#}\x92R\xdc\xa2\xab\xab\xcb\x8d.~\x9f\x82a\xbf\xec]k\xdb\xc55\x1d\xa4\x00\xe8\x03\x94\xb0\x91\x14\xf0\x9ec\x9a\x9ay\xfeP\xe3\x07J\x00\xb5\xbd\xba\xcb(\xf5\xdb\xab\x1a'

如我们所见,在散列的中间有一个 '\x00',但没有在末尾。 flask_bcrypt 检测到这是一个 ValueError 异常:

if b"\x00" in password:
    raise ValueError("password may not contain NUL bytes")

我知道 '\x00' 是一个保留字符,并且可能是由于散列长度扩展攻击引起的攻击向量。然而,我不认为我做了任何不寻常的事情。在将散列传递给我丢失的 bcrypt 或 flask_bcrypt 之前,是否有最佳实践对其进行清理,或者是否有另一种类型的字节编码应该与密码一起使用?

拒绝普通密码会很奇怪,因为它与所使用的身份验证库的派生哈希冲突.. 非常感谢任何帮助或建议。谢谢!

解决方法

BCrypt 旨在散列用户密码,这与例如SHA 旨在像文件一样散列二进制输入。用户输入的密码实际上从不包含\0字符,毕竟是用户自己决定密码,而不是试图利用安全漏洞的黑客。

换句话说,您应该直接将密码作为字符串传入,并避免将其转换为二进制值的 UTF-8 编码。