我的目标:获取纯文本密码并生成可用于 Fernet 加密的 32 字节令牌。
到目前为止我尝试过的:
>>> from cryptography.fernet import Fernet
>>> import argon2
>>> import base64
>>> hash = argon2.hash_password('abc'.encode(), hash_len=32)
>>> hash
b'$argon2i$v=19$m=65536,t=3,p=4$ee2ZpEZ5Q58HwIT91xQxgw$QrzxXCLBOnuzLgVPoccIPcaeF4mS4uvmrRBFzNXZbxw'
>>> Fernet(hash)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3/dist-packages/cryptography/fernet.py", line 34, in __init__
raise ValueError(
ValueError: Fernet key must be 32 url-safe base64-encoded bytes.
然后我尝试过:
>>> b64_hash = base64.urlsafe_b64decode(hash)
>>> b64_hash
b'j\xb8(\x9fh\xaf\xd7\xd9'
>>> Fernet(b64_hash)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3/dist-packages/cryptography/fernet.py", line 32, in __init__
key = base64.urlsafe_b64decode(key)
File "/usr/lib/python3.10/base64.py", line 133, in urlsafe_b64decode
return b64decode(s)
File "/usr/lib/python3.10/base64.py", line 87, in b64decode
return binascii.a2b_base64(s)
binascii.Error: Incorrect padding
所以,我已经修复了第一个错误,但现在又出现了另一个(类似的)错误。 这是什么问题?
我找到的解决方案是使用
hash_secret_raw
函数:
import base64
import argon2
from cryptography.fernet import Fernet
password = "abc"
key = argon2.low_level.hash_secret_raw(password.encode("utf-8"), salt=b"somesalt", time_cost=1, memory_cost=8, parallelism=1, hash_len=32, type=argon2.low_level.Type.D)
assert 32 == len(key)
b64_key = base64.urlsafe_b64encode(key)
cipher = Fernet(b64_key)
基本上,
hash_password
函数返回实际的哈希值以及哈希验证所需的更多信息。所以hash_password
的结果大于32字节。 hash_secret_raw
仅返回实际的 32 字节哈希值。