
本文介绍了如何使用 Python 的 argon2 库生成 256 位的哈希值。通过示例代码展示了设置 hash_len 参数为 32 字节(256 位)后,实际输出长度为 43 的原因,并提供了解决方案,即解码 Base64 编码后的哈希值。
在使用 Argon2 进行密码哈希时,我们通常需要指定输出哈希值的长度。argon2 库中的 PasswordHasher 类提供了一个 hash_len 参数,用于设置哈希值的字节长度。期望生成 256 位的哈希值时,通常会将 hash_len 设置为 32,因为 32 字节等于 256 位。
然而,在实际操作中,可能会遇到一个问题:即使将 hash_len 设置为 32,最终得到的哈希值字符串的长度却不是 32,而是更长,例如 43。这是因为 argon2 库默认会将生成的二进制哈希值进行 Base64 编码,以便于存储和传输。Base64 编码会将每 3 个字节的数据编码成 4 个字节,因此编码后的字符串长度会比原始字节长度更长。
以下是一个示例代码:
from argon2 import PasswordHasher
import binascii
password = "abc123"
salt = b'b8b17dbde0a2c67707342c459f6225ed'
hasher = PasswordHasher(
salt_len=len(salt),
hash_len=32,
)
hasherOutput = hasher.hash(password, salt = salt)
hash_string = hasherOutput.split('$')[-1]
print(f"Encoded Hash Length: {len(hash_string)}")
print(f"Encoded Hash: {hash_string}")
# 解码 Base64 编码后的哈希值
try:
decoded_hash = binascii.a2b_base64(hash_string)
except binascii.Error:
# Base64 字符串长度不是 4 的倍数,需要添加 padding
missing_padding = len(hash_string) % 4
if missing_padding:
hash_string += '=' * (4 - missing_padding)
decoded_hash = binascii.a2b_base64(hash_string)
print(f"Decoded Hash Length: {len(decoded_hash)}")
print(f"Decoded Hash: {decoded_hash.hex()}")代码解释:
- 导入必要的库: 导入 argon2 用于哈希计算,binascii 用于 Base64 解码。
- 设置密码和盐: 定义要哈希的密码和盐值。盐值应该足够随机且唯一。
- 创建 PasswordHasher 对象: 实例化 PasswordHasher 对象,设置 salt_len 和 hash_len 参数。
- 进行哈希: 调用 hash() 方法对密码进行哈希,得到哈希结果。
- 提取哈希字符串: 从哈希结果中提取 Base64 编码后的哈希字符串。hasherOutput 是一个包含 Argon2 算法标识、版本、参数和哈希值的字符串,通过 split('$')[-1] 可以提取出哈希值部分。
- 解码 Base64: 使用 binascii.a2b_base64() 函数对 Base64 编码的哈希字符串进行解码,得到原始的 32 字节哈希值。
- 处理 Base64 Padding: Base64 编码要求输入长度是 3 的倍数。如果编码后的字符串长度不是 4 的倍数,需要添加 = 字符进行 padding。 代码中添加了 try...except 块来处理这种情况。
- 打印结果: 打印 Base64 编码后的哈希值长度和内容,以及解码后的哈希值长度和内容(以十六进制格式显示)。
注意事项:
- 盐值(salt)必须是随机的、唯一的,并且长度应该足够长,以防止彩虹表攻击。
- hash_len 参数应该根据实际需求进行设置。如果需要更高的安全性,可以增加 hash_len 的值。
- 在存储哈希值时,应该同时存储盐值,以便在验证密码时使用相同的盐值进行哈希。
- Base64 解码时,如果遇到 Incorrect padding 错误,通常是因为 Base64 字符串的长度不是 4 的倍数,需要添加适当的 padding。
总结:
在使用 argon2 库生成指定长度的哈希值时,需要注意 Base64 编码的影响。如果需要获得原始的字节哈希值,需要对 Base64 编码后的字符串进行解码。通过使用 binascii.a2b_base64() 函数,可以方便地将 Base64 编码的哈希值解码为原始的字节数据。 此外,注意处理 Base64 编码可能需要的 padding,确保解码过程正确无误。










