diff --git a/lib_cryptomator_utils/cryptomator.py b/lib_cryptomator_utils/cryptomator.py index 74b6ac6..c99f95f 100644 --- a/lib_cryptomator_utils/cryptomator.py +++ b/lib_cryptomator_utils/cryptomator.py @@ -17,7 +17,10 @@ from .aes import aes_siv_decrypt, aes_siv_encrypt from .b64url import b64url_decode, b64url_encode -from Crypto.Cipher import AES +from cryptography.hazmat.primitives.ciphers import Cipher +from cryptography.hazmat.primitives.ciphers.aead import AESGCM +from cryptography.hazmat.primitives.ciphers.algorithms import AES +from cryptography.hazmat.primitives.ciphers.modes import GCM from cryptography.hazmat.primitives.kdf.scrypt import Scrypt from cryptography.hazmat.primitives.keywrap import aes_key_unwrap, InvalidUnwrap @@ -228,8 +231,7 @@ def decrypt_file(vault_path, primary_master_key, hashed_directory_id, filename): header_tag = ciphertext_header[-16:] # Decrypt header to obtain the content key - cipher = AES.new(primary_master_key, AES.MODE_GCM, nonce=header_nonce) - plaintext_header = cipher.decrypt_and_verify(header_payload, header_tag) + plaintext_header = AESGCM(primary_master_key).decrypt(header_nonce, header_payload + header_tag, None) content_key = plaintext_header[8:] # Decrypt file in chunks corresponding to 32 KiB plaintext @@ -241,15 +243,13 @@ def decrypt_file(vault_path, primary_master_key, hashed_directory_id, filename): chunk_payload = ciphertext_chunk[12:-16] chunk_tag = ciphertext_chunk[-16:] - # Chunk is encrypted with AES-GCM - cipher = AES.new(content_key, AES.MODE_GCM, nonce=chunk_nonce) + # Chunk is encrypted with AES-GCM - chunk number and header nonce are passed as AAD + # cryptography.hazmat.primitives.ciphers.aead.AESGCM does not support multiple AAD so must do this manually + cipher = Cipher(AES(content_key), GCM(chunk_nonce, chunk_tag)).decryptor() + cipher.authenticate_additional_data(struct.pack('>Q', chunk_num)) + cipher.authenticate_additional_data(header_nonce) + plaintext_chunk = cipher.update(chunk_payload) + cipher.finalize() - # Chunk number and header nonce are passed as AAD - # Contrary to the Cryptomator documentation, chunk number is a 64-bit not 32-bit integer - https://github.com/cryptomator/docs/pull/54 - cipher.update(struct.pack('>Q', chunk_num)) - cipher.update(header_nonce) - - plaintext_chunk = cipher.decrypt_and_verify(chunk_payload, chunk_tag) plaintext.extend(plaintext_chunk) return bytes(plaintext)