# compatibile Windows 11 # compatibile Ubuntu 24.10 # compatibile python 3.12.7 import os from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.primitives import serialization from cryptography.exceptions import InvalidSignature from cryptography.hazmat.backends import default_backend def generate_keypair(bits: int = 2048): """ Genera una coppia di chiavi RSA (pubblica, privata) usando la libreria cryptography. Args: bits: La dimensione della chiave in bit (default: 2048). Returns: Una tupla (private_key, public_key). """ private_key = rsa.generate_private_key( public_exponent=65537, key_size=bits, backend=default_backend() ) public_key = private_key.public_key() return private_key, public_key def serialize_key(key, private: bool = False, password: str = None) -> bytes: """ Serializza una chiave RSA (privata o pubblica) in formato PEM. Args: key: La chiave da serializzare (oggetto PrivateKey o PublicKey). private: True se la chiave è privata, False se è pubblica. password: La password per proteggere la chiave privata (opzionale). Returns: La chiave serializzata in formato PEM (bytes). """ if private: if password: encryption_algorithm = serialization.BestAvailableEncryption(password.encode()) else: encryption_algorithm = serialization.NoEncryption() pem = key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=encryption_algorithm ) else: # Chiave pubblica pem = key.public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo ) return pem def deserialize_key(pem: bytes, private: bool = False, password: str = None): """ Deserializza una chiave RSA (privata o pubblica) da formato PEM. Args: pem: La chiave serializzata in formato PEM (bytes). private: True se la chiave è privata, False se è pubblica. password: La password per la chiave privata (opzionale). Returns: L'oggetto chiave (PrivateKey o PublicKey). """ if private: if password: key = serialization.load_pem_private_key( pem, password=password.encode(), backend=default_backend() ) else: key = serialization.load_pem_private_key( pem, password=None, backend=default_backend() ) else: #Chiave Pubblica key = serialization.load_pem_public_key( pem, backend=default_backend() ) return key def encrypt(message: bytes, public_key) -> bytes: """ Cifra un messaggio usando RSA-OAEP con la chiave pubblica. Args: message: Il messaggio da cifrare (bytes). public_key: La chiave pubblica RSA (oggetto PublicKey). Returns: Il crittogramma (bytes). """ ciphertext = public_key.encrypt( message, padding.OAEP( mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None ) ) return ciphertext def decrypt(ciphertext: bytes, private_key) -> bytes: """ Decifra un crittogramma usando RSA-OAEP con la chiave privata. Args: ciphertext: Il crittogramma da decifrare (bytes). private_key: La chiave privata RSA (oggetto PrivateKey). Returns: Il messaggio originale (bytes). """ plaintext = private_key.decrypt( ciphertext, padding.OAEP( mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None ) ) return plaintext def sign(message: bytes, private_key) -> bytes: """ Firma digitalmente un messaggio usando RSA-PSS con la chiave privata. Args: message: Il messaggio da firmare (bytes). private_key: La chiave privata RSA (oggetto PrivateKey). Returns: La firma digitale (bytes). """ signature = private_key.sign( message, padding.PSS( mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH ), hashes.SHA256() ) return signature def verify(message: bytes, signature: bytes, public_key) -> bool: """ Verifica una firma digitale usando RSA-PSS con la chiave pubblica. Args: message: Il messaggio originale (bytes). signature: La firma digitale (bytes). public_key: La chiave pubblica RSA (oggetto PublicKey). Returns: True se la firma è valida, False altrimenti. """ try: public_key.verify( signature, message, padding.PSS( mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH ), hashes.SHA256() ) return True # La verifica è andata a buon fine except InvalidSignature: return False # La firma non è valida except Exception as e: print(f"Errore durante la verifica: {e}") return False def clear_screen(): """Pulisce lo schermo della console (sia Windows che Unix-like).""" os.system('cls' if os.name == 'nt' else 'clear') def main(): """Funzione principale del programma dimostrativo.""" clear_screen() print("=" * 50) print(" Dimostrazione dell'algoritmo RSA con 'cryptography'") print("=" * 50) # 1. Generazione delle chiavi print("\n1. Generazione delle chiavi...") bits = 0 while bits < 2048: try: bits = int(input(" Inserisci la dimensione delle chiavi in bit (>= 2048, es. 2048): ")) if bits < 2048: print(" Errore: la dimensione minima consigliata è 2048 bit.") except ValueError: print(" Errore: inserisci un numero intero.") private_key, public_key = generate_keypair(bits) print(" Chiavi generate.") # Serializzazione delle chiavi (per mostrarle/salvarle) private_pem = serialize_key(private_key, private=True) public_pem = serialize_key(public_key) print("\n Chiave privata (PEM, non protetta):") print(private_pem.decode()) # Decodifica da bytes a stringa per la stampa print("\n Chiave pubblica (PEM):") print(public_pem.decode()) # 2. Cifratura print("\n2. Cifratura...") message = input(" Inserisci il messaggio da cifrare (testo): ").encode('utf-8') ciphertext = encrypt(message, public_key) print(f" Crittogramma (bytes): {ciphertext.hex()}") # Visualizza come esadecimale # 3. Decifratura print("\n3. Decifratura...") decrypted_message = decrypt(ciphertext, private_key) print(f" Messaggio decifrato: {decrypted_message.decode('utf-8')}") # 4. Firma print("\n4. Firma digitale...") message_to_sign = input(" Inserisci il messaggio da firmare: ").encode('utf-8') signature = sign(message_to_sign, private_key) print(f" Firma (bytes): {signature.hex()}") # Visualizza come esadecimale # 5. Verifica print("\n5. Verifica della firma...") is_valid = verify(message_to_sign, signature, public_key) if is_valid: print(" [SUCCESS] La firma è valida.") else: print(" [ERRORE] La firma NON è valida.") # Deserializzazione (esempio) print("\n6. Deserializzazione delle chiavi (esempio)") deserialized_private_key = deserialize_key(private_pem, private=True) deserialized_public_key = deserialize_key(public_pem) # Verifica che le chiavi deserializzate siano uguali alle originali if private_key == deserialized_private_key: print (" Chiave privata deserializzata correttamente.") if public_key == deserialized_public_key: print(" Chiave pubblica deserializzata correttamente.") print("=" * 50) if __name__ == "__main__": main()