我正在尝试创建一个用于加密/解密不同文件的程序。我的代码没有问题,我只是不知道如何保存通过我的程序加密的每个文件的密码。
用户可以使用密码加密他的文件,当他试图解密它时,必须有一条消息通知他密码错误,因为当他使用错误密码时,程序会生成一个解密文件,这将仍然无法阅读。
我正在尝试创建一个用于加密/解密不同文件的程序。我的代码没有问题,我只是不知道如何保存通过我的程序加密的每个文件的密码。
用户可以使用密码加密他的文件,当他试图解密它时,必须有一条消息通知他密码错误,因为当他使用错误密码时,程序会生成一个解密文件,这将仍然无法阅读。
你做错了!但这没关系,业余密码学是我们所有人开始和学习的地方。请注意,除非您让独立第三方对其进行审核,否则您的加密软件将不安全,即便如此,他们也不做任何保证。不要将您自己的爱好加密货币用于任何重要的事情!并且不要让其他人使用它而不确保他们知道它只是一个玩具!
想象一下,您有一个文件,上面写着“10:00 攻击”。加密,类似于aWJiaWtzIGliIDEzOjAw. 您的敌人可能知道您正在发送攻击消息,但不知道密码。但是,他们可以做的是更改一个字节。如果消息更改为aWJiaWtzIGliIDazOjAw(E替换为a),它突然说:“在 03:00 攻击”。
如您所见,即使是盲目地修改密文,也可能对攻击者(敌人)有利。您希望在检测到修改的情况下进行身份验证加密。这也解决了您的密码问题。
您不需要将密码存储在文件中,因为如果他们输入错误的密码,身份验证检查将失败。软件会注意到解密后的文本与原始文本不同,你就会知道它是错误的。
还有一些关于为什么应该使用经过身份验证的加密的更多详细信息:
网上有很多关于如何进行身份验证加密的资源。寻找一些好的方法是 AES+HMAC,或 AES 在认证模式,如 GCM 或 OCB。这篇 Wikipedia 文章是一个很好的介绍,并包含指向您可能可以使用的算法的指针:https ://en.wikipedia.org/wiki/Authenticated_encryption
作为一个例子,让我们考虑前面的密文:aWJiaWtzIGliIDEzOjAw. 现在我们使用 SHA-256 对其进行HMAC,这给了我们3be635.... 我使用了一个随机在线站点来计算 HMAC,并使用了与加密时相同的密码。(作为对读者的挑战,请尝试打破它:)。它只是一个字符。)我们可以将两者存储在一起:aWJiaWtzIGliIDEzOjAw|3be635. 当用户尝试解密内容时,他们输入密码,您可以再次计算 HMAC,如果不匹配,您就知道消息被篡改,或者他们的密码不正确。
代码基本上是:
# Encrypt
password = user_input()
plaintext = "attack at 10:00"
ciphertext = encrypt(method = "AES-256-CTR", key = password, data = plaintext)
auth_code = hmac(method = "SHA-256", key = password, data = ciphertext
write_file(name = "encrypted", data = base64(ciphertext) + "|" + auth_code)
# Decrypt
password = user_input()
ciphertext, auth_code = read_file(name = "encrypted").split("|")
computed_auth_code = hmac(method = "SHA-256", key = password, data = ciphertext)
if computed_auth_code == auth_code:
plaintext = decrypt(method = "AES-256-CTR", key = password, data = ciphertext)
print(base64_decode(plaintext))
到目前为止一切顺利,但是...
这种方法允许攻击者非常快速地猜出密码。HMAC 操作需要几微秒来计算,因此攻击者可以在标准计算机上每秒进行许多猜测。代码非常简单:
ciphertext, auth_code = read_file(name = "encrypted").split("|")
for password in load_file("password_database.txt"):
if auth_code == hmac(method = "SHA-256", key = password, data = ciphertext):
print("The password is " + password)
因为for循环中唯一的操作是hmac(...)和快速比较,所以非常快。
在将用户密码用于任何操作之前,您应该应用慢速密钥派生函数 (KDF)。问题中回答了如何最好地做到这一点:如何安全地散列密码?.
您的代码现在应该如下所示:
password = user_input()
password = argon2(iterations = 1_000_000, memory = 100_000_000, data = password)
# Below here, the normal encryption/decryption code
现在,攻击者的代码必须如下所示:
ciphertext, auth_code = read_file(name = "encrypted").split("|")
for password in load_file("password_database.txt"):
password = argon2(iterations = 1_000_000, memory = 100_000_000, data = password)
if auth_code == hmac(method = "SHA-256", key = password, data = ciphertext):
print("The password is " + password)
现在攻击者必须做这个 argon2 的事情,这非常慢。如果在您的计算机上需要 1 秒,那么在他们的计算机上也将需要大约 1 秒(可能快一点,也可能慢一点)。这意味着攻击者每秒只能猜测一次密码。这样安全多了!当然,攻击者可以使用 100 台计算机,但这是一笔巨大的投资,他们仍然每秒只有 100 次猜测,而不是每秒数百万甚至数十亿次。