18 from typing
import Generator
19 from pathlib
import Path
21 from cryptography.hazmat.primitives
import padding
22 from cryptography.hazmat.primitives.ciphers
import Cipher, algorithms, modes
24 from .constants
import DEFAULT_CHUNK_SIZE, AES_KEY_SIZE, IV_SIZE, AES_BLOCK_SIZE
25 from .utils
import DataBuffer
31 Implements functionality for decrypting a stream of bytes
35 def __init__(self, key: bytes, iv: bytes, chunkSize: int = DEFAULT_CHUNK_SIZE) ->
None:
36 if len(key) != AES_KEY_SIZE:
37 raise ValueError(f
"AES key size: {len(key)}, but {AES_KEY_SIZE} expected")
39 if len(iv) != IV_SIZE:
40 raise ValueError(f
"IV size: {len(iv)}, but {IV_SIZE} expected")
43 self.
_decryptor_decryptor = Cipher(algorithms.AES256(self.
_key_key), modes.CBC(iv)).decryptor()
44 self.
_buffer_buffer = DataBuffer()
49 def feed(self, data: bytes) -> Generator[bytes,
None,
None]:
51 Decrypts the data using AES 256.
56 data which should be decrypted
60 Generator[bytes, None, None] -> yields decrypted data in chunks
63 self.
_buffer_buffer.append(data)
71 Decrypts any remaining data using AES 256.
75 bytes -> decrypted data
79 chunk = self.
_buffer_buffer.getRemaining()
84 unpadder = padding.PKCS7(AES_BLOCK_SIZE * 8).unpadder()
85 return unpadder.update(chunk) + unpadder.finalize()
94 def decryptFile(key: bytes, sourcePath: Path, destinationPath: Path) ->
None:
96 Decrypts a file using AES 256.
101 key which will be used for decrypting
103 path to the file which will be decrypted
104 destinationPath : Path
105 path to the decrypted file
108 with sourcePath.open(
"rb")
as source, destinationPath.open(
"wb")
as destination:
109 iv = source.read(IV_SIZE)
112 while (chunk := source.read(DEFAULT_CHUNK_SIZE)):
113 for decryptedData
in decryptor.feed(chunk):
114 destination.write(decryptedData)
116 destination.write(decryptor.flush())
Generator[bytes, None, None] feed(self, bytes data)