问题
This code works for a file myfile
which fits in RAM:
import Crypto.Random, Crypto.Cipher.AES # pip install pycryptodome
nonce = Crypto.Random.new().read(16)
key = Crypto.Random.new().read(16) # in reality, use a key derivation function, etc. ouf of topic here
cipher = Crypto.Cipher.AES.new(key, Crypto.Cipher.AES.MODE_GCM, nonce=nonce)
out = io.BytesIO()
with open('myfile', 'rb') as g:
s = g.read()
ciphertext, tag = cipher.encrypt_and_digest(s)
out.write(nonce)
out.write(ciphertext)
out.write(tag)
But how to encrypt a 64 GB file using this technique?
Obviously, the g.read(...)
should use a smaller buffer-size, e.g. 128 MB.
But then, how does it work for the crypto part? Should we keep a (ciphertext, tag)
for each 128-MB chunk?
Or is it possible to have only one tag
for the whole file?
回答1:
As mentioned in @PresidentJamesK.Polk's comment, this seems to be the solution:
out.write(nonce)
while True:
block = g.read(65536)
if not block:
break
out.write(cipher.encrypt(block))
out.write(cipher.digest()) # 16-byte tag at the end of the file
The only problem is that, when reading back this file for decryption, stopping at the end minus 16 bytes is a bit annoying.
Or maybe one should do this:
out.write(nonce)
out.seek(16, 1) # go forward of 16 bytes, placeholder for tag
while True:
...
...
out.seek(16)
out.write(cipher.digest()) # write the tag at offset #16 of the output file
?
来源:https://stackoverflow.com/questions/64951915/encrypt-a-big-file-that-does-not-fit-in-ram-with-aes-gcm