如何使用 Python 加密大文件?
Posted
技术标签:
【中文标题】如何使用 Python 加密大文件?【英文标题】:How to encrypt large file using Python? 【发布时间】:2021-11-17 14:45:10 【问题描述】:我正在尝试加密大于 1GB 的文件。我不想把它全部读到记忆中。我为这项任务选择了 Fernet (cryptography.fernet),因为它是最受推荐的(比非对称解决方案更快)。
我生成了密钥。然后我创建了一个脚本来加密:
key = Fernet(read_key())
with open(source, "rb") as src, open(destination, "wb") as dest:
for chunk in iter(lambda: src.read(4096), b""):
encrypted = key.encrypt(chunk)
dest.write(encrypted)
用于解密:
key = Fernet(read_key())
with open(source, "rb") as src, open(destination, "wb") as dest:
for chunk in iter(lambda: src.read(4096), b""):
decrypted = key.decrypt(chunk)
dest.write(decrypted)
加密有效 - 不足为奇,但解密却不行。 首先,我认为它可能会起作用,但事实并非如此。我猜块大小在加密时会增加,然后当我读取 4096 字节时,它不是一个完整的加密块。我尝试解密时出错:
Traceback (most recent call last):
File "/redacted/path/venv/lib/python3.7/site-packages/cryptography/fernet.py", line 119, in _verify_signature
h.verify(data[-32:])
File "/redacted/path/venv/lib/python3.7/site-packages/cryptography/hazmat/primitives/hmac.py", line 74, in verify
ctx.verify(signature)
File "/redacted/path/venv/lib/python3.7/site-packages/cryptography/hazmat/backends/openssl/hmac.py", line 75, in verify
raise InvalidSignature("Signature did not match digest.")
cryptography.exceptions.InvalidSignature: Signature did not match digest.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/redacted/path/main.py", line 63, in <module>
decrypted = key.decrypt(chunk)
File "/redacted/path/venv/lib/python3.7/site-packages/cryptography/fernet.py", line 80, in decrypt
return self._decrypt_data(data, timestamp, time_info)
File "/redacted/path/venv/lib/python3.7/site-packages/cryptography/fernet.py", line 137, in _decrypt_data
self._verify_signature(data)
File "/redacted/path/venv/lib/python3.7/site-packages/cryptography/fernet.py", line 121, in _verify_signature
raise InvalidToken
cryptography.fernet.InvalidToken
有没有办法解决这个问题?也许有比 fernet 更好(更简单)的解决方案?
【问题讨论】:
这能回答你的问题吗? Cryptography token object raises exception and cannot decrypt even though the tokens are identical @buran 不。我生成了一次密钥并将其存储在我使用 read_key() 从中读取的文件中。我之前在寻找答案时看到了这个问题。我找不到任何有用的东西。 【参考方案1】:Fernet 不应该以流媒体方式使用。他们在文档中解释了这一点:
From the documentation (last section):
限制
Fernet 非常适合加密可轻松放入内存的数据。作为一项设计功能,它不会暴露未经身份验证的字节。这意味着完整的消息内容必须在内存中可用,这使得 Fernet 目前通常不适合非常大的文件。
【讨论】:
【参考方案2】:由于内存的限制,我们可以使用块来加密和解密。
#
# encrypt
#
key = b'Ke0Ft_85-bXQ8GLOOsEI6JeT2mD-GeI8pkcP_re8wio='
in_file_name = 'plain.txt'
out_file_name = 'encypted.txt'
with open(in_file_name, "rb") as fin, open(out_file_name, "wb") as fout:
while True:
block = fin.read(524288)
if not block:
break
f = Fernet(key)
output = f.encrypt(block)
fout.write(output)
#
# decrypt
#
in_file_name = 'encrypted.txt'
out_file_name = 'plain2.txt'
with open(in_file_name, "rb") as fin, open(out_file_name, "wb") as fout:
while True:
block = fin.read(699148)
if not block:
break
f = Fernet(key)
output = f.decrypt(block)
fout.write(output)
【讨论】:
以上是关于如何使用 Python 加密大文件?的主要内容,如果未能解决你的问题,请参考以下文章