from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC from cryptography.hazmat.primitives import hashes from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import padding from base64 import b64encode, b64decode import os class AESCipher: def __init__(self, key: str): self.backend = default_backend() salt = os.urandom(16) kdf = PBKDF2HMAC( algorithm=hashes.SHA256(), length=32, salt=salt, iterations=100000, backend=self.backend ) self.key = kdf.derive(key.encode()) self.iv = os.urandom(16) def encrypt(self, plaintext: str) -> str: padder = padding.PKCS7(algorithms.AES.block_size).padder() padded_data = padder.update(plaintext.encode()) + padder.finalize() cipher = Cipher(algorithms.AES(self.key), modes.CBC(self.iv), backend=self.backend) encryptor = cipher.encryptor() encrypted_data = encryptor.update(padded_data) + encryptor.finalize() return b64encode(self.iv + encrypted_data).decode('utf-8') def decrypt(self, ciphertext: str) -> str: encrypted_data = b64decode(ciphertext) iv = encrypted_data[:16] encrypted_data = encrypted_data[16:] cipher = Cipher(algorithms.AES(self.key), modes.CBC(iv), backend=self.backend) decryptor = cipher.decryptor() padded_plaintext = decryptor.update(encrypted_data) + decryptor.finalize() unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder() plaintext = unpadder.update(padded_plaintext) + unpadder.finalize() return plaintext.decode('utf-8')