修复使用 Fernet Token 解密时出现的无效签名问题。

4

我对Python和加密模块cryptography比较新,所以我正在学习加密和解密的基础知识。 当我在同一个程序中加密文件并进行解密时,一切都运作正常,但如果我尝试仅对一个预先加密的文件运行解密代码(当然我使用了相同的密钥),我会得到InvalidSignature错误,随后是InvalidToken。

现在,我认为由于某种原因密钥不匹配,但它们确实是相同的。 然后我想,也许我将字符串传递给函数而不是字节,或者可能存在某些转换错误可能会改变加密的消息。但加密-解密代码可以工作,所以我无法找出为什么仅解密应该遇到错误。 最后,我查看了解密函数的源代码,并尝试弄清楚时间戳是否与我收到的错误有关,但由于经验不够,我无法获得相关信息。 这是加密-解密代码:程序通过用户提供密码来加密并打印一个文件,可立即进行解密。

import base64
import os
from cryptography.fernet import Fernet
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC

print("Insert password: ")
password_str = input()
password = password_str.encode()
salt = os.urandom(16)

kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=salt, 
iterations=100000, backend=default_backend())

key = base64.urlsafe_b64encode(kdf.derive(password))
f = Fernet(key)

message = "A really secret message. Not for prying eyes.".encode()
token = f.encrypt(message)

file = open("text_encrypted.txt", "wb")
file.write(token)
file.close()

file = open("text_encrypted.txt", "rb")
data = file.read()
file.close()

token = f.decrypt(data)

file = open("text_decrypted.txt", "wb")
file.write(token)
file.close()

现在,这个方案可以很好地运行,我得到了包含加密和解密信息的两个文件。 如果我删除:

message = "A really secret message. Not for prying eyes.".encode()
token = f.encrypt(message)

file = open("text_encrypted.txt", "wb")
file.write(token)
file.close()

我应该只留下解密代码以便在一个之前已加密的文件上使用,该文件应该可以通过相同的密码进行解密。

显然我可能遗漏了一些微不足道的东西,因为这引发了无效签名和无效令牌的问题。谢谢您的帮助。

1个回答

1
您正在使用的加密密钥是由PBKDF2生成的。为了让PBKDF2返回相同的加密密钥,它必须获得完全相同的参数。这包括盐,在您的示例中,每次都是随机生成的。
您需要将生成的盐与加密文件一起存储,以便以后能够解密它。

你说得完全正确,我没有注意到随机生成器。这很愚蠢,因为这是我知道的东西,但出于某种原因,我开始考虑更奇特的问题。 无论如何,当寻找不匹配的密钥时,我走在了正确的轨道上,但我错误地排除了那个选项。 对于其他人来说:基本上,urandom没有“种子”,因此每次都会生成不同的盐。另一方面,带有种子的随机函数在调用时产生相同的伪随机数集,因此应该产生相同的盐。 谢谢你,安德鲁! - MarcoR
@MarcoR,只是为了明确:使用urandom是正确的方式,盐需要由CSPRNG生成。种子PRNG几乎肯定不具有密码学安全性。您应该存储并重复使用生成的盐,它可以是数据库中的明文或附加到加密文件中。 - Andrew Morozko
1
对于我所考虑的应用程序,盐值并不是那么重要,所以我甚至可以避免使用它,但感谢您的评论,我同意种子随机数给代码带来的熵要少得多。我会按照您的建议存储盐值,这样我就能更多地了解密码学模块。 - MarcoR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接