I'm getting an cryptography.fernet.InvalidToken
error only when I want decrypt data while using functools.partial
for iterate into a file.
key = Fernet.generate_key()
print(key)
cypher = Fernet(key)
def encryypt():
with open('file.pdf', 'rb') as f, open('file2.pdf', 'wb') as target_f:
for _bytes in iter(partial(f.read, 10*2048), ''):
encrypt_data = cypher.encrypt(_bytes)
target_f.write(encrypt_data)
if not _bytes:break
target_f.close()
def decryypt() :
with open('file2.pdf', 'rb') as ff, open('file3.pdf', 'wb') as target_ff:
for __bytes in iter(partial(ff.read, 10*2048), ''):
decrypt_data = cypher.decrypt(__bytes)
target_ff.write(decrypt_data)
if not __bytes:break
encryypt()
decryypt()
The encrypt() function works perfectly, but fails for decrypt() with this error:
Traceback (most recent call last):
File "C:\Users\#\#\.venv\Lib\site-packages\cryptography\fernet.py", line 134, in _verify_signature
h.verify(data[-32:])
cryptography.exceptions.InvalidSignature: Signature did not match digest.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "c:\Users\#\#\Bin2\Start\test.py", line 43, in <module>
decryypt()
File "c:\Users\#\#\Bin2\Start\test.py", line 39, in decryypt
decrypt_data = cypher.decrypt(__bytes)
^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\#\#\.venv\Lib\site-packages\cryptography\fernet.py", line 91, in decrypt
return self._decrypt_data(data, timestamp, time_info)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\#\#\.venv\Lib\site-packages\cryptography\fernet.py", line 152, in _decrypt_data
self._verify_signature(data)
File "C:\Users\#\#\.venv\Lib\site-packages\cryptography\fernet.py", line 136, in _verify_signature
raise InvalidToken
cryptography.fernet.InvalidToken
Same key and same cypher are used, I'm sure it's a problem with the iteration.
So like President James K.Polk said, Fernet it's not meant for encrypt big date or streaming data.
From the doc :
Limitations :
Fernet is ideal for encrypting data that easily fits in memory. As a design feature it does not expose unauthenticated bytes. This means that the complete message contents must be available in memory, making Fernet generally unsuitable for very large files at this time.
So the only way to encrypt data through iteration with Fernet is to chunk data then encrypt it.
In the following code, we will chunk the file into blocks of 6MB, then encrypt it.
in_file = 'linux.zip'
enc_file = 'linux_enc.zip'
out_file = 'linux_out.zip'
key = Fernet.generate_key()
cypher = Fernet(key)
def encryypt():
with open(in_file, 'rb') as f, open(enc_file, 'wb') as target_f:
for _bytes in iter(partial(f.read,600000), ''):
if not _bytes:break
encrypted_data = cypher.encrypt(_bytes)
target_f.write(encrypted_data)
print(f'encrypted block size:{str(len(encrypted_data))}')
target_f.close()
def decryypt() :
with open(enc_file, 'rb') as ff, open(out_file, 'wb') as target_ff:
for __bytes in iter(partial(ff.read,800100), ''):
if not __bytes:break
decrypted_data = cypher.decrypt(__bytes)
target_ff.write(decrypted_data)
print(f'decrypted block size:{str(len(decrypted_data))}')
target_ff.close()
encryypt()
decryypt()
And for decryption we need to increase the chunk size because the file is bigger after the encryption.
For encrypt a chunk of 6000000 bytes, we have to decrypt a chunk of 8000100 bytes.