Avoid using PyCryptodome for AES-GCM decryption of file contents
This removes all PyCryptodome dependencies
This commit is contained in:
parent
2af1d5385b
commit
8aa4c8dc48
@ -17,7 +17,10 @@
|
|||||||
from .aes import aes_siv_decrypt, aes_siv_encrypt
|
from .aes import aes_siv_decrypt, aes_siv_encrypt
|
||||||
from .b64url import b64url_decode, b64url_encode
|
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.kdf.scrypt import Scrypt
|
||||||
from cryptography.hazmat.primitives.keywrap import aes_key_unwrap, InvalidUnwrap
|
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:]
|
header_tag = ciphertext_header[-16:]
|
||||||
|
|
||||||
# Decrypt header to obtain the content key
|
# Decrypt header to obtain the content key
|
||||||
cipher = AES.new(primary_master_key, AES.MODE_GCM, nonce=header_nonce)
|
plaintext_header = AESGCM(primary_master_key).decrypt(header_nonce, header_payload + header_tag, None)
|
||||||
plaintext_header = cipher.decrypt_and_verify(header_payload, header_tag)
|
|
||||||
content_key = plaintext_header[8:]
|
content_key = plaintext_header[8:]
|
||||||
|
|
||||||
# Decrypt file in chunks corresponding to 32 KiB plaintext
|
# 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_payload = ciphertext_chunk[12:-16]
|
||||||
chunk_tag = ciphertext_chunk[-16:]
|
chunk_tag = ciphertext_chunk[-16:]
|
||||||
|
|
||||||
# Chunk is encrypted with AES-GCM
|
# Chunk is encrypted with AES-GCM - chunk number and header nonce are passed as AAD
|
||||||
cipher = AES.new(content_key, AES.MODE_GCM, nonce=chunk_nonce)
|
# 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)
|
plaintext.extend(plaintext_chunk)
|
||||||
|
|
||||||
return bytes(plaintext)
|
return bytes(plaintext)
|
||||||
|
Loading…
Reference in New Issue
Block a user