import sys from cryptography.hazmat.primitives import serialization, hashes from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.backends import default_backend # function to decrypt data using a symmetric key def decrypt_symmetric(key, ciphertext): # generate a random IV iv = ciphertext[:16] # decipher the data using AES in CFB mode ciphertext = ciphertext[16:] cipher = Cipher(algorithms.AES(key), modes.CFB(iv), backend=default_backend()) decryptor = cipher.decryptor() return decryptor.update(ciphertext) + decryptor.finalize() # function that calls and combines the symmetric and asymmetric decryption def decrypt_hybrid(private_key, encrypted_data): # extract the encrypted symmetric key and the encrypted data (remember that the data is symmetric + asymmetric) encrypted_symmetric_key = encrypted_data[:private_key.key_size // 8] encrypted_data = encrypted_data[private_key.key_size // 8:] # decrypt the symmetric key using the RSA private key symmetric_key = private_key.decrypt( encrypted_symmetric_key, padding.OAEP( mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None ) ) # decrypt the data using the decrypted symmetric key return decrypt_symmetric(symmetric_key, encrypted_data) # main function to decrypt the file def decrypt_file(private_key, encrypted_file, decrypted_file): with open(encrypted_file, 'rb') as f: encrypted_content = f.read() decrypted_content = decrypt_hybrid(private_key, encrypted_content) with open(decrypted_file, 'wb') as f: f.write(decrypted_content) # function to load a private key from a file def load_private_key(file, passwd=None): if passwd is not None: passwd = passwd.encode('utf-8') try: with open(file, 'rb') as key_file: private_key = serialization.load_pem_private_key( key_file.read(), password=passwd, ) except ValueError as e: raise ValueError("Error: The password is not valid.") from e return private_key