La crittografia non è un unico strumento: è tre famiglie di algoritmi con obiettivi completamente diversi. Confonderli porta a usarli nel modo sbagliato. Un developer che salva le password con AES invece di bcrypt, o che firma dati con SHA-256 pensando che basti, ha un problema di sicurezza concreto.
Se parti da zero, l'introduzione ai concetti base è un buon punto di partenza prima di continuare qui.
Crittografia simmetrica: una chiave per tutto
Nella crittografia simmetrica, chi cifra e chi decifra usano la stessa chiave segreta. L'algoritmo dominante oggi è AES (Advanced Encryption Standard), adottato dal NIST nel 2001 come successore di DES.
AES lavora a blocchi di 128 bit e supporta chiavi da 128, 192 o 256 bit. La modalità CBC (Cipher Block Chaining) era lo standard de facto per anni, ma GCM (Galois/Counter Mode) l'ha sostituita perché unisce cifratura e autenticazione in un'unica operazione.
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
key = AESGCM.generate_key(bit_length=256)
aesgcm = AESGCM(key)
nonce = os.urandom(12)
plaintext = b"messaggio segreto"
ciphertext = aesgcm.encrypt(nonce, plaintext, None)
recovered = aesgcm.decrypt(nonce, ciphertext, None)
print(recovered) # b'messaggio segreto'
AES-GCM risolve qualcosa che CBC da solo non affronta: garantisce che il ciphertext non sia stato manomesso in transito. Con CBC puro, un attaccante può modificare i blocchi cifrati in modi prevedibili senza conoscere la chiave.
Il punto debole della crittografia simmetrica è la distribuzione della chiave: come la condividi con l'altro lato in modo sicuro? È qui che entra l'asimmetrica.
Crittografia asimmetrica: due chiavi, zero condivisione
La crittografia asimmetrica usa una coppia di chiavi: una pubblica (distribuibile liberamente) e una privata (che non lascia mai il sistema). Quello che cifri con la pubblica si decifra solo con la privata.
RSA è l'algoritmo più noto, ma nelle implementazioni moderne Ed25519 è preferito per firme digitali: è più veloce, produce chiavi più corte e ha una superficie di attacco minore rispetto a RSA con le curve ellittiche.
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
private_key = Ed25519PrivateKey.generate()
public_key = private_key.public_key()
message = b"questo documento e' autentico"
signature = private_key.sign(message)
# chiunque abbia la chiave pubblica puo' verificare
public_key.verify(signature, message) # solleva InvalidSignature se manomesso
Nella pratica, la crittografia asimmetrica non cifra dati in volume: è troppo lenta per quello. TLS la usa solo per lo scambio iniziale della chiave simmetrica di sessione. Dopo quel handshake, tutto viaggia con AES.
Le chiavi SSH che usi per autenticarti ai server sono esattamente coppie Ed25519 o RSA. Come generarle e configurare l'autenticazione senza password.
Hashing: trasformazione a senso unico
Un hash non è cifratura. SHA-256 trasforma dati di qualsiasi dimensione in un digest di 256 bit fisso, e questo processo è irreversibile by design: partendo dal digest non puoi risalire all'input originale.
import hashlib
digest = hashlib.sha256(b"qualsiasi dato").hexdigest()
print(digest)
# a2c3f4... sempre lo stesso per lo stesso input
SHA-256 è adatto per verificare l'integrità di file, generare identificatori deterministici, o costruire strutture come Merkle tree. Per le password è la scelta sbagliata.
Per le password serve un algoritmo lento, con salt automatico e fattore di costo configurabile. bcrypt e Argon2 sono progettati per questo: ogni chiamata impiega deliberatamente 100-300ms, rendendo il brute force computazionalmente costoso anche con hardware moderno.
import bcrypt
password = b"password_utente"
hashed = bcrypt.hashpw(password, bcrypt.gensalt(rounds=12))
# verifica in fase di login
bcrypt.checkpw(password, hashed) # True
bcrypt.checkpw(b"sbagliata", hashed) # False
SHA-256 su password è un errore diffuso. GPU farm moderne craccano miliardi di hash SHA-256 al secondo. bcrypt con rounds=12 scende a poche migliaia, rendendo il brute force ordini di grandezza più costoso.
Quale usare e quando
| Problema | Algoritmo consigliato | Note |
|---|---|---|
| Cifrare dati con chiave condivisa | AES-GCM 256 bit | nonce unico per ogni operazione |
| Scambio chiave, firma digitale | Ed25519, RSA-OAEP | RSA minimo 2048 bit |
| Integrità file, checksum | SHA-256, SHA-3 | evitare MD5 e SHA-1 |
| Password storage | bcrypt, Argon2id | mai SHA-256 diretto |
| Derivare chiave da password | Argon2id, PBKDF2 | per proteggere archivi cifrati |
La crittografia moderna di applicazioni come WhatsApp o Signal usa tutti e tre i livelli insieme: asimmetrica per lo scambio iniziale delle chiavi, simmetrica per i messaggi, hashing per le firme e l'integrità. Come la crittografia end-to-end funziona in un caso reale.