以下代码生成示例 Fernet 密钥,并报告长度为 44。
from cryptography.fernet import Fernet
generated_key = Fernet.generate_key()
print(f'Example generated key: {generated_key}')
print(f'Length of example key: {len(generated_key)}')
输出是(例如)
Example generated key: b'U4f1fCfXWlz7pQ-7WdZKmCY-VtSAln7R-hhvF6qgYa4='
Length of example key: 44
快速浏览一下这个参考文献告诉我们,
=
是一个填充字符。如果不包括这个 =
符号,实际上有 43 个字符。
U4f1fCfXWlz7pQ-7WdZKmCY-VtSAln7R-hhvF6qgYa4
1 2 3 4 5 6 7 8 9 10 11
U4f1 fCfX Wlz7 pQ-7 WdZK mCY- VtSA ln7R -hhv F6qg Ya4
即 10 个 4 个字符的块加上 3 个字符 = 43。
我正在尝试使用以下代码生成示例密钥:
key = "1234567890123456789012345678901234567890"
print(f'Encryption key is: {key}')
base64_key = base64.b64encode(key.encode('utf-8'))
print(f'Base64 encoded key is: {base64_key}')
print(f'Length of base64 encoded key: {len(base64_key)}')
if len(base64_key) > 43:
base64_key = base64_key[:43]
print(f'Truncating key to length {43}: {base64_key}')
print(f'Length of base64 encoded key is now {len(base64_key)}')
elif len(base64_key) < required_key_length_characters:
print(f'error: key is too short')
raise RuntimeError(f'key too short')
fernet_instance = Fernet(base64_key)
但是这会产生以下输出和异常:
Encryption key is: 1234567890123456789012345678901234567890
Base64 encoded key is: b'MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MA=='
Length of base64 encoded key: 56
Truncating key to length 43: b'MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI'
Length of base64 encoded key is now 43
binascii.Error: Incorrect padding
确实,手动破解填充
base64_key = base64_key + b'='
解决了问题。
我的代码产生的异常表示
ValueError: Fernet key must be 32 url-safe base64-encoded bytes
32 字节 = 256 位。每个base64编码的字符是6位。
256 / 6 = 42.6666...或 43(如果四舍五入的话)。这与
Fernet.generate_key()
生成的密钥长度相匹配。
43 个字符的密钥包含足够的位来进行 256 位的加密。那么为什么这不起作用呢?
它实际上有略多于 256 位的信息。 43 * 6 = 258
44 个字符的密钥包含足够的位来进行 256 位的加密,并且它与 4 字节边界对齐。但是,它仍然失败并产生以下异常:
ValueError: Fernet key must be 32 url-safe base64-encoded bytes
因此,即使 4 字节边界是一些奇怪的任意要求(也许是一个错误?),那么这应该可以工作,特别是考虑到长度为 43 的密钥并不具有正好 256 位的信息。有258个。
鉴于上述情况,这并不奇怪。
如果您根本不截断密钥,则会产生相同的异常。
截断到 43 个字符,然后在末尾添加填充字符以将长度增加到 44 的逻辑似乎是任意的。
有没有更好的方法使用密码样式输入来生成这种密钥?
一种方便的方法是使用固定长度哈希算法(例如 sha256)对密码进行哈希处理。我稍后会添加确切的代码。