def decrypt_filedata(data, keys): '''Decrypts a file from Send''' # The last 16 bytes / 128 bits of data is the GCM tag # https://www.w3.org/TR/WebCryptoAPI/#aes-gcm-operations :- # 7. Let ciphertext be equal to C | T, where '|' denotes concatenation. data.seek(-16, 2) tag = data.read() # now truncate the file to only contain encrypted data data.seek(-16, 2) data.truncate() data.seek(0) plain = tempfile.NamedTemporaryFile(mode='w+b', delete=False) pbar = progbar(fileSize(data)) obj = Cryptodome.Cipher.AES.new(keys.encryptKey, Cryptodome.Cipher.AES.MODE_GCM, keys.encryptIV) prev_chunk = b'' for chunk in iter(lambda: data.read(CHUNK_SIZE), b''): plain.write(obj.decrypt(prev_chunk)) pbar.update(len(chunk)) prev_chunk = chunk plain.write(obj.decrypt_and_verify(prev_chunk, tag)) data.close() pbar.close() plain.seek(0) return plain
def test_fileSize(testdata_1M): # open the test file and move the pointer to check fileSize() does not change it with open(str(testdata_1M), 'rb') as f: f.seek(123) # check the correct size is returned for the 1MiB file assert fileSize(f) == 1024 * 1024 # check the pointer has not moved assert f.tell() == 123
def encrypt_file(file, keys=secretKeys()): '''Encrypt file data with the same method as the Send browser/js client''' key = keys.encryptKey iv = keys.encryptIV encData = tempfile.SpooledTemporaryFile(max_size=SPOOL_SIZE, mode='w+b') cipher = Cryptodome.Cipher.AES.new(key, Cryptodome.Cipher.AES.MODE_GCM, iv) pbar = progbar(fileSize(file)) for chunk in iter(lambda: file.read(CHUNK_SIZE), b''): encData.write(cipher.encrypt(chunk)) pbar.update(len(chunk)) pbar.close() encData.write(cipher.digest()) file.close() encData.seek(0) return encData