Il 15 ottobre 2026 la domanda non è più se migrare alla crittografia post-quantum, ma quanto in fretta farlo. OpenSSL 3.5 porta ML-KEM dentro il motore TLS più usato al mondo, e i tre standard NIST (FIPS 203, 204, 205) sono pronti per la produzione da oltre un anno. Chi scrive backend, API o semplici servizi HTTPS si trova già oggi davanti a una scelta concreta: aggiornare la libreria e ottenere protezione post-quantum quasi gratis, oppure restare su una configurazione che un domani andrà rifatta sotto pressione, con meno tempo per testare. In questo tutorial costruiamo un laboratorio completo: verifica della versione OpenSSL, un server TLS 1.3 con scambio di chiavi ibrido, un container Docker riproducibile e un piccolo progetto Python che usa ML-KEM-768 direttamente. Dodici passi, codice testabile riga per riga, nessuna teoria fine a sé stessa.
Perché la crittografia post-quantum non è più teoria
Nell’agosto 2024 il NIST ha pubblicato tre standard definitivi: FIPS 203 per ML-KEM, FIPS 204 per ML-DSA e FIPS 205 per SLH-DSA. Da allora l’agenzia americana li definisce pronti per l’adozione immediata, non più sperimentali. Il motivo della fretta ha un nome tecnico preciso: harvest now, decrypt later. Un attaccante può registrare oggi il traffico cifrato con RSA o con curve elittiche classiche e aspettare che un computer quantistico sufficientemente potente lo decifri in futuro. Per dati che devono restare segreti per anni, come cartelle sanitarie, segreti industriali, contratti pluriennali o comunicazioni diplomatiche, il rischio è già presente, anche se il computer quantistico capace di romperle non esiste ancora. Non serve che la minaccia sia operativa oggi: basta che il traffico catturato adesso resti leggibile per chi lo intercetta, in archivio, per anni.
Questo è anche il motivo per cui molte aziende che gestiscono infrastrutture critiche, dal settore bancario alle telecomunicazioni, hanno iniziato a inserire clausole sul supporto post-quantum nei capitolati di gara già nel 2025, prima ancora che un obbligo normativo specifico lo imponesse. Chi fornisce software a questi settori, anche come piccolo team di sviluppo in Italia o altrove in Europa, si troverà la richiesta nel capitolato prima che nella legge.
I numeri sull’adozione raccontano un settore che si muove, ma lentamente. Secondo una ricerca di Utimaco del 2025, “il 20% delle organizzazioni ha già iniziato la migrazione alla crittografia post-quantum, mentre il 34% prevede di iniziarla entro 1-3 anni”. Lo stesso studio segnala che “il 63% delle organizzazioni che stanno lavorando alla migrazione PQC preferisce un approccio ibrido, combinando crittografia classica e post-quantum”: esattamente il modello che OpenSSL 3.5 adotta di default con il gruppo X25519MLKEM768. Un’indagine separata di DigiCert aggiunge un dato più scomodo: “solo il 5% delle imprese ha implementato la crittografia quantum-safe, nonostante il 69% riconosca il rischio che i computer quantistici possano compromettere gli standard di cifratura attuali entro cinque anni”, come riportato dal report DigiCert sul quantum readiness gap.
Il NIST, nel frattempo, non si è fermato al primo gruppo di algoritmi. Nel marzo 2025 ha selezionato HQC come quinto meccanismo di key establishment, pensato come alternativa non basata su reticoli a ML-KEM. Il draft dello standard è atteso nel corso del 2026, con finalizzazione prevista per il 2027, un dettaglio utile per chi pianifica roadmap di sicurezza a più anni. Lo stato del processo è documentato nelle slide ufficiali del progetto NIST PQC, aggiornate nel 2026.
Per orientarsi tra le date, conviene avere sotto mano una cronologia sintetica delle pubblicazioni principali che riguardano direttamente questo tutorial, dalla finalizzazione degli standard fino alla release di OpenSSL che li rende utilizzabili senza provider esterni.
| Data | Evento |
|---|---|
| Agosto 2024 | NIST pubblica FIPS 203 (ML-KEM), FIPS 204 (ML-DSA) e FIPS 205 (SLH-DSA) come standard finali |
| Aprile 2025 | Rilascio di OpenSSL 3.5.0, prima release LTS con ML-KEM nativo nel provider predefinito |
| Marzo 2025 | Il NIST pubblica l’IR 8545 e seleziona HQC come quinto algoritmo di key establishment |
| 5 agosto 2025 | Rilascio di OpenSSL 3.5.2 |
| 18 settembre 2025 | NIST pubblica SP 800-227 con le raccomandazioni per i meccanismi KEM |
| 2026 | Debian 13 “trixie” distribuisce OpenSSL 3.5.6 via apt, atteso anche il draft dello standard HQC |
Guardando questa sequenza, la parte sorprendente non è la velocità del NIST, che segue un processo pubblico e documentato da anni, ma la rapidità con cui OpenSSL ha reso quegli standard disponibili nella pratica. Meno di otto mesi sono passati tra la finalizzazione di FIPS 203 e una release LTS pronta per la produzione, un ritmo raro per cambiamenti così profondi in una libreria usata da miliardi di dispositivi.
Cos’è ML-KEM e cosa cambia davvero con OpenSSL 3.5
ML-KEM (Module-Lattice-Based Key-Encapsulation Mechanism) è un meccanismo di incapsulamento di chiave, non un algoritmo di cifratura dei dati. Serve a una cosa sola: far concordare a due parti un segreto condiviso su un canale pubblico, senza che un osservatore possa ricostruirlo. Deriva da CRYSTALS-Kyber e si basa sul problema matematico Module Learning With Errors, considerato resistente sia agli attacchi classici che a quelli eseguiti con un computer quantistico. RSA, Diffie-Hellman, ECDH, ECDSA ed EdDSA restano invece algoritmi vulnerabili a un computer quantistico sufficientemente potente, secondo la documentazione tecnica NIST più recente.
Prima di OpenSSL 3.5, usare ML-KEM in un handshake TLS richiedeva un provider esterno come OQS (Open Quantum Safe), con tutte le complicazioni di compilazione e manutenzione che ne derivano. OpenSSL 3.5, rilasciato come release LTS nell’aprile 2025, include ML-KEM, ML-DSA e SLH-DSA nel provider predefinito. Il cambio più concreto per chi scrive software è questo: il gruppo ibrido X25519MLKEM768, che combina la curva classica X25519 con ML-KEM-768, è abilitato come key share predefinito in TLS 1.3. In pratica, molte applicazioni ottengono protezione post-quantum senza toccare una riga di codice, semplicemente aggiornando la libreria sottostante.
Perché ibrido e non ML-KEM puro? Perché nessuno vuole scommettere l’intera sicurezza di una connessione su un algoritmo pubblicato da appena due anni. Combinando X25519 (studiato e attaccato per oltre un decennio senza risultati) con ML-KEM-768, un avversario deve rompere entrambi i problemi matematici per leggere il traffico. È lo stesso principio di difesa in profondità che la maggioranza delle organizzazioni intervistate da Utimaco dice di preferire, e che questo tutorial userà come configurazione predefinita in ogni esempio.
Vale la pena chiarire anche cosa un KEM non fa. Non cifra documenti, non protegge file a riposo, non sostituisce AES per il traffico applicativo dopo l’handshake. Una volta che client e server hanno concordato il segreto condiviso tramite ML-KEM, quel segreto diventa la base per derivare le chiavi di sessione che poi cifrano davvero i dati, tipicamente con AES-256-GCM o ChaCha20-Poly1305, esattamente come accadeva prima con un segreto derivato da X25519. ML-KEM cambia solo il modo in cui quel primo segreto viene stabilito, rendendolo resistente anche a un futuro computer quantistico.
Prerequisiti e software necessari
Il laboratorio è stato progettato per funzionare su Linux (Ubuntu 24.04 o Debian 13), ma le stesse istruzioni OpenSSL valgono su macOS con Homebrew e su WSL2 per chi usa Windows. Debian 13 “trixie” merita una menzione speciale: il suo repository stabile distribuisce già il pacchetto OpenSSL in versione 3.5.6, quindi su quella distribuzione puoi saltare la compilazione manuale e passare diretto ai passi di verifica. Su Ubuntu 24.04 la versione di sistema è precedente alla 3.5, quindi la compilazione dal codice sorgente resta necessaria.
| Componente | Versione richiesta | Note |
|---|---|---|
| OpenSSL | 3.5.0 o superiore (consigliata 3.5.6) | 3.5.0 è la prima release LTS con ML-KEM nativo, di aprile 2025 |
| Sistema operativo | Ubuntu 24.04 o Debian 13 | Debian 13 (“trixie”) distribuisce già OpenSSL 3.5.6 via apt |
| Python | 3.11 o successivo | Serve per gli script di esempio e per i binding ML-KEM |
| liboqs-python | ultima versione disponibile su pip | Binding Python al progetto Open Quantum Safe |
| Docker | ultima versione stabile | Per containerizzare il laboratorio in modo riproducibile |
| Strumenti di build | build-essential, perl, make | Necessari solo se compili OpenSSL dal codice sorgente |
Un avvertimento prima di partire: tutto quello che segue va eseguito in un ambiente di test o in una macchina virtuale dedicata. Compilare una versione alternativa di OpenSSL su un sistema di produzione può rompere altri servizi che dipendono dalla libreria di sistema. I passi 1-7 lavorano direttamente sulla macchina host per capire i comandi, il passo 8 sposta tutto dentro un container isolato.
Non serve hardware particolare: ML-KEM-768 è pensato per essere veloce anche su CPU modeste, molto più rapido da calcolare rispetto a RSA-4096 per esempio. Una macchina virtuale con due core e 2 GB di RAM è più che sufficiente per completare tutti i dodici passi di questo tutorial, compresa la build di OpenSSL dal codice sorgente, che è la parte più lenta ma resta comunque questione di pochi minuti su hardware recente.
Passo 1: controlla quale versione di OpenSSL stai usando
Prima di installare qualsiasi cosa, verifica cosa hai già. Molti ambienti Ubuntu 24.04 si fermano a OpenSSL 3.0.x, troppo vecchio per ML-KEM nativo.
openssl version -a
apt-cache policy openssl
openssl list -tls1_3 -groups
Se il terzo comando restituisce un errore di sintassi o non elenca gruppi legati a ML-KEM, la tua installazione è troppo vecchia. In quel caso passa direttamente al passo 2. Se invece vedi già X25519MLKEM768 tra i gruppi disponibili, puoi saltare la compilazione e andare al passo 3. Il secondo comando, apt-cache policy openssl, è utile anche per capire da quale repository arriva il tuo pacchetto attuale: se vedi un repository di terze parti o un backport, meglio documentarlo prima di sovrascrivere qualcosa che altri processi del sistema potrebbero dare per scontato.
Passo 2: installa o compila OpenSSL 3.5.6
Su Debian 13 basta il gestore dei pacchetti, perché il repository stabile porta già la 3.5.6:
sudo apt update
sudo apt install -y openssl
openssl version
Su Ubuntu 24.04, dove il pacchetto di sistema resta più vecchio, serve compilare la libreria a parte, senza sovrascrivere quella usata dal resto del sistema:
sudo apt update
sudo apt install -y build-essential checkinstall zlib1g-dev perl wget
wget https://github.com/openssl/openssl/releases/download/openssl-3.5.6/openssl-3.5.6.tar.gz
tar -xzf openssl-3.5.6.tar.gz
cd openssl-3.5.6
./Configure linux-x86_64 --prefix=/opt/openssl-3.5 --openssldir=/opt/openssl-3.5/ssl
make -j$(nproc)
sudo make install
export PATH=/opt/openssl-3.5/bin:$PATH
export LD_LIBRARY_PATH=/opt/openssl-3.5/lib64:$LD_LIBRARY_PATH
openssl version
Installare in /opt/openssl-3.5 invece che sovrascrivere /usr/bin/openssl è una scelta deliberata: tieni la libreria di sistema intatta e usi quella nuova solo quando esplicitamente la metti nel PATH. Per rendere il cambio permanente in questa sessione di lavoro, aggiungi le due righe export al file .bashrc.
Passo 3: conferma il supporto nativo a ML-KEM
Con la libreria giusta attiva, rifai la verifica del passo 1. Questa volta il gruppo ibrido deve apparire nell’elenco:
openssl list -tls1_3 -groups
Se il comando viene rifiutato dalla tua build, il fallback è interrogare l’help del client TLS e cercare manualmente la stringa:
openssl s_client -help 2>&1 | grep -E 'groups|curves'
Un dettaglio da non trascurare: ML-KEM qui è usato per lo scambio di chiavi della sessione TLS, non per autenticare il server. L’autenticazione resta compito del certificato X.509, che nel prossimo passo genereremo ancora con una curva elittica classica. Sono due problemi distinti, e la migrazione post-quantum di uno non implica automaticamente quella dell’altro, un punto su cui torneremo nella sezione sugli errori comuni.
Passo 4: genera certificato e chiave per i test TLS
Per il laboratorio locale basta un certificato autofirmato. Usiamo ECDSA su curva P-256, scelta comune e ben supportata, non ML-DSA: la firma del certificato non è l’oggetto di questo tutorial.
openssl req -x509 -newkey ec \
-pkeyopt ec_paramgen_curve:P-256 \
-keyout server.key \
-out server.crt \
-sha256 -days 365 -nodes \
-subj "/CN=localhost"
Il flag -nodes lascia la chiave privata senza passphrase, comodo per i test automatici ma da evitare in qualunque scenario reale. In produzione quella chiave va protetta con una passphrase o custodita in un HSM. Nota che qui la curva P-256 serve solo a firmare il certificato che autentica il server: non ha niente a che fare con ML-KEM, che entrerà in gioco solo al momento dell’handshake, nel passo successivo.
Passo 5: avvia il server TLS 1.3 con il gruppo ibrido
Con certificato e chiave pronti, avviamo un server TLS 1.3 minimale forzando il gruppo post-quantum:
openssl s_server \
-accept 4433 \
-cert server.crt \
-key server.key \
-tls1_3 \
-groups X25519MLKEM768 \
-www
Il flag -www fa rispondere il server con una pagina di debug che include i dettagli della connessione, utile in questa fase. Lascia il terminale aperto: lo userai come controparte per il passo successivo.
Passo 6: verifica il gruppo negoziato con s_client
In un secondo terminale, connettiti e chiedi esplicitamente il gruppo ibrido:
openssl s_client \
-connect 127.0.0.1:4433 \
-tls1_3 \
-groups X25519MLKEM768 \
-brief < /dev/null
Se vuoi vedere il dettaglio completo dello scambio, incluso il key share negoziato, sostituisci -brief con -trace e cerca nel log le stringhe X25519MLKEM768 e ServerHello:
openssl s_client \
-connect 127.0.0.1:4433 \
-tls1_3 \
-groups X25519MLKEM768 \
-trace < /dev/null 2>&1 | grep -A2 -i "key share"
Il formato esatto della riga di output varia a seconda della build di OpenSSL, e non esiste un unico comando di grep che funzioni identico su tutte le versioni 3.5.x. Tratta questo passo come un controllo visivo più che come un test automatico rigido: l'automazione vera arriva al passo 11.
Passo 7: confronta la connessione classica e quella post-quantum
Per capire cosa cambia davvero, ripeti l'esperimento forzando il solo gruppo classico, sia sul server che sul client. Interrompi il server del passo 5 e riavvialo così:
openssl s_server \
-accept 4433 \
-cert server.crt \
-key server.key \
-tls1_3 \
-groups X25519 \
-www
openssl s_client \
-connect 127.0.0.1:4433 \
-tls1_3 \
-groups X25519 \
-brief < /dev/null
Entrambe le connessioni devono riuscire senza errori: questo dimostra che il passaggio al post-quantum, almeno lato OpenSSL, è una questione di configurazione e non di riscrittura del codice applicativo. La differenza di dimensione del messaggio ClientHello tra i due casi esiste, perché la chiave pubblica ML-KEM-768 è più grande di quella X25519, ma al momento non esiste una cifra ufficiale univoca documentata per ogni combinazione di estensioni e catena di certificati. Evita quindi di citare un numero di byte preciso finché non lo misuri tu stesso con tcpdump o Wireshark sul tuo scenario esatto.
Passo 8: porta il laboratorio in un container Docker
Per rendere l'esperimento riproducibile su qualunque macchina, costruiamo un'immagine basata su Debian 13, che come visto nei prerequisiti porta già OpenSSL 3.5.6 dal repository stabile. Niente compilazione dentro il container, solo apt.
FROM debian:13-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
openssl python3 python3-pip python3-venv ca-certificates \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY . /app
RUN openssl version
EXPOSE 4433
CMD ["openssl", "s_server", "-accept", "4433", \
"-cert", "server.crt", "-key", "server.key", \
"-tls1_3", "-groups", "X25519MLKEM768:X25519", "-www"]
Nota l'ordine dei gruppi nel CMD: X25519MLKEM768:X25519. Mettere il gruppo ibrido per primo lo rende preferito quando entrambe le parti lo supportano, ma lascia comunque una via di fallback per client che ancora non conoscono ML-KEM. Scegliere Debian 13 come base, invece di continuare con la build manuale usata nel passo 2, ha un vantaggio preciso: l'immagine resta aggiornabile con un normale apt-get upgrade quando Debian pubblicherà la prossima patch di OpenSSL, senza bisogno di ricompilare nulla a mano dentro ogni container. Costruisci ed esegui con:
docker build -t pq-tls-lab .
docker run --rm -p 4433:4433 pq-tls-lab
Passo 9: genera ed esegui l'encapsulation ML-KEM-768 in Python
OpenSSL gestisce ML-KEM dentro il protocollo TLS, ma può essere istruttivo vedere il meccanismo di incapsulamento isolato dal resto. Il progetto Open Quantum Safe pubblica binding Python installabili via pip:
python3 -m venv venv
source venv/bin/activate
pip install liboqs-python
Con il pacchetto installato, questo script genera una coppia di chiavi ML-KEM-768, incapsula un segreto condiviso dal lato server e lo decapsula dal lato client, verificando che coincidano:
import oqs
ALGORITHM = "ML-KEM-768"
with oqs.KeyEncapsulation(ALGORITHM) as client_kem:
public_key = client_kem.generate_keypair()
with oqs.KeyEncapsulation(ALGORITHM) as server_kem:
ciphertext, shared_secret_server = server_kem.encap_secret(public_key)
shared_secret_client = client_kem.decap_secret(ciphertext)
print("Algoritmo:", ALGORITHM)
print("Dimensione chiave pubblica (byte):", len(public_key))
print("Dimensione ciphertext (byte):", len(ciphertext))
print("Segreti coincidono:", shared_secret_client == shared_secret_server)
I nomi esatti dei metodi possono cambiare leggermente tra versioni di liboqs-python. Se lo script restituisce un errore di attributo, controlla il README del pacchetto installato sulla tua macchina prima di modificare la logica: è il tipo di dettaglio che cambia più in fretta della documentazione che lo descrive.
Il numero 768 nel nome dell'algoritmo non è decorativo: ML-KEM esiste in tre varianti parametriche, ML-KEM-512, ML-KEM-768 e ML-KEM-1024, con livelli di sicurezza crescenti e chiavi via via più grandi. ML-KEM-768 è il parametro scelto da OpenSSL 3.5 per il gruppo ibrido predefinito perché offre un compromesso ritenuto adeguato tra sicurezza e overhead per il traffico TLS generico. Chi ha requisiti di sicurezza più stringenti, per esempio per proteggere comunicazioni governative o militari, può valutare ML-KEM-1024, pagando il prezzo di chiavi pubbliche e ciphertext ancora più grandi.
Passo 10: collega ML-KEM a un piccolo servizio HTTPS Python
Il modulo ssl della libreria standard Python non parla direttamente di ML-KEM, ma si appoggia alla libreria OpenSSL installata sul sistema. Se quella libreria è la 3.5 con il gruppo ibrido come predefinito, anche un server HTTPS scritto con poche righe di Python eredita la stessa protezione senza nessuna configurazione aggiuntiva:
import http.server
import ssl
ADDRESS = ("0.0.0.0", 4433)
httpd = http.server.HTTPServer(ADDRESS, http.server.SimpleHTTPRequestHandler)
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain(certfile="server.crt", keyfile="server.key")
context.minimum_version = ssl.TLSVersion.TLSv1_3
httpd.socket = context.wrap_socket(httpd.socket, server_side=True)
httpd.serve_forever()
Per confermare che Python stia davvero usando il gruppo ibrido, riusa il comando del passo 6 puntandolo su questa porta. Se il tuo interprete Python è compilato contro una OpenSSL più vecchia (capita spesso con build Python installate tramite pyenv senza ricompilare contro la nuova libreria), il modulo ssl continuerà a negoziare solo gruppi classici anche se il sistema ha OpenSSL 3.5 installato altrove. È uno degli errori più comuni della sezione successiva.
Passo 11: scrivi un controllo automatico da usare in CI/CD
Verificare manualmente ogni volta che un deploy mantenga il supporto post-quantum non è sostenibile. Questo script bash si può aggiungere a una pipeline di continuous integration e fallisce esplicitamente se il server non negozia più il gruppo atteso:
#!/usr/bin/env bash
set -euo pipefail
HOST="${1:-127.0.0.1}"
PORT="${2:-4433}"
OUTPUT=$(openssl s_client -connect "${HOST}:${PORT}" -tls1_3 \
-groups X25519MLKEM768 < /dev/null 2>&1 || true)
if echo "$OUTPUT" | grep -qi "X25519MLKEM768"; then
echo "OK: connessione post-quantum confermata su ${HOST}:${PORT}"
exit 0
else
echo "FALLITO: nessuna traccia di X25519MLKEM768 nella sessione"
exit 1
fi
Aggiungi questo script come step dopo il deploy di staging, prima della promozione in produzione. Un deploy che silenziosamente torna a X25519 classico, per esempio perché un'immagine base è stata aggiornata male, viene scoperto in minuti e non in un audit di sicurezza fatto un anno dopo.
Nelle pipeline più mature, questo controllo viene eseguito su più ambienti in sequenza: prima in staging contro l'immagine appena costruita, poi in produzione subito dopo il deploy, e infine come controllo periodico ogni poche ore tramite un job pianificato. I tre livelli catturano problemi diversi: il primo blocca una regressione prima che raggiunga gli utenti, il secondo conferma che il rollout è andato a buon fine, il terzo intercetta cambiamenti di configurazione fatti manualmente al di fuori della pipeline, che altrimenti passerebbero inosservati fino al prossimo deploy.
Passo 12: la struttura finale del progetto completo
Messi insieme, i passi precedenti formano un progetto autonomo e riutilizzabile. Questa è la struttura delle cartelle che dovresti avere a questo punto:
pq-tls-lab/
├── Dockerfile
├── server.crt
├── server.key
├── server.py
├── kem_demo.py
├── requirements.txt
├── ci_check.sh
└── README.md
Il file requirements.txt contiene solo una riga, liboqs-python, mentre ci_check.sh è lo script del passo 11 rifinito con permessi di esecuzione (chmod +x ci_check.sh). Con questa struttura puoi eseguire tutto il laboratorio con tre comandi: build dell'immagine, avvio del container, esecuzione del controllo automatico contro la porta esposta. È lo scheletro minimo che puoi estendere con un vero backend applicativo dietro il server TLS.
Il README.md non è decorativo: documenta quale versione esatta di OpenSSL è stata usata per generare il certificato e avviare i test, perché nei mesi successivi qualcuno (magari tu stesso) dovrà capire perché un comportamento è cambiato dopo un aggiornamento. Annotare la versione in un file di testo semplice costa trenta secondi oggi e può far risparmiare ore di debug quando Debian pubblicherà la prossima patch di OpenSSL 3.5.
Tabella comparativa: crittografia classica contro post-quantum
Prima di passare agli errori comuni, vale la pena fissare le differenze principali tra la famiglia di algoritmi classici e quella post-quantum che li sta affiancando, non ancora sostituendo del tutto.
| Algoritmo | Funzione | Base matematica | Standard NIST | Stato a ottobre 2026 |
|---|---|---|---|---|
| RSA / ECDH / X25519 | Scambio di chiavi classico | Fattorizzazione / logaritmo discreto | Nessuno specifico PQC | Vulnerabile a computer quantistico sufficientemente potente |
| ML-KEM-768 | Scambio di chiavi post-quantum | Module Learning With Errors (reticoli) | FIPS 203 | Standard finale, nativo in OpenSSL 3.5 |
| ML-DSA | Firma digitale post-quantum | Reticoli (CRYSTALS-Dilithium) | FIPS 204 | Standard finale, supportato in OpenSSL 3.5 |
| SLH-DSA | Firma digitale post-quantum | Funzioni hash | FIPS 205 | Standard finale, alternativa più conservativa a ML-DSA |
| HQC | Scambio di chiavi post-quantum | Codici correttori (non reticoli) | In preparazione | Selezionato marzo 2025, draft nel 2026, finale nel 2027 |
HQC merita attenzione per un motivo strategico più che tecnico: usa una base matematica diversa da ML-KEM. Se in futuro emergesse una debolezza nei reticoli, avere uno standard di riserva basato su un problema matematico completamente diverso è un'assicurazione, non una ridondanza inutile. Vale lo stesso ragionamento che ha portato il NIST a standardizzare sia ML-DSA, basato sui reticoli, sia SLH-DSA, basato su funzioni hash, per le firme digitali: due strade matematiche distinte riducono il rischio che un singolo risultato di crittoanalisi comprometta tutto in un colpo.
Errori comuni da evitare durante la migrazione
- Confondere ML-KEM con la firma del certificato. ML-KEM protegge lo scambio di chiavi della sessione, non autentica il server. Il certificato X.509 può restare firmato con ECDSA per anni mentre il key exchange passa già al post-quantum: sono due migrazioni indipendenti.
- Forzare solo il gruppo ibrido senza fallback. Configurare
-groups X25519MLKEM768da solo, come abbiamo fatto nei passi didattici, rompe la connessione con qualunque client che non supporti ancora ML-KEM. In produzione la lista va sempre con un gruppo classico come riserva, come nel Dockerfile del passo 8. - Non pinnare la versione di OpenSSL nelle immagini di produzione. Una build "latest" può silenziosamente aggiornare o retrocedere la versione di OpenSSL tra un deploy e l'altro. Fissa sempre un tag di versione esplicito, sia per l'immagine Docker che per i pacchetti apt quando possibile.
- Dare per scontato che tutta la catena supporti i nuovi gruppi. Load balancer, CDN, reverse proxy e librerie client intermedie potrebbero terminare il TLS prima che il traffico arrivi al tuo server, negoziando ancora solo algoritmi classici. Verifica ogni anello della catena, non solo l'origine.
- Saltare la misurazione delle prestazioni prima del rollout su larga scala. Le chiavi pubbliche e i ciphertext ML-KEM sono più grandi di quelli classici. Su connessioni ad alta latenza o con molti handshake al secondo, l'impatto va misurato con il proprio traffico reale, non assunto da benchmark generici trovati online.
Risoluzione dei problemi: gli errori più frequenti
- "unknown option -groups" su s_server o s_client. La tua build di OpenSSL è precedente alla 3.5. Torna al passo 2 e verifica di aver esportato correttamente PATH e LD_LIBRARY_PATH verso la versione nuova.
- Il client negozia X25519 anche con -groups X25519MLKEM768 impostato. Controlla che anche il server supporti il gruppo: se il server è ancora su una libreria vecchia, il client ricade automaticamente sul gruppo disponibile più sicuro che entrambi conoscono.
- pip install liboqs-python fallisce con errori di compilazione. Il pacchetto richiede la libreria C liboqs sottostante e strumenti di build come cmake. Installa prima
cmake,ninja-builde un compilatore C funzionante, poi riprova. - Connection refused su 127.0.0.1:4433. Il server del passo 5 o 8 non è in esecuzione, oppure il firewall locale blocca la porta. Verifica con
ss -tlnp | grep 4433prima di dare la colpa a OpenSSL. - Il modulo ssl di Python non mostra ML-KEM anche con OpenSSL 3.5 installato. Il tuo interprete Python è probabilmente collegato a una copia diversa, più vecchia, della libreria. Controlla con
python3 -c "import ssl; print(ssl.OPENSSL_VERSION)"e, se necessario, ricompila Python contro la nuova OpenSSL. - Docker build fallisce durante l'installazione dei pacchetti apt. Verifica che l'immagine base sia effettivamente
debian:13-slime non una cache locale di una versione precedente: eseguidocker pull debian:13-slimper forzare l'aggiornamento prima del build. - Permission denied aprendo la porta 443 con openssl s_server. Le porte sotto 1024 richiedono privilegi elevati su Linux. Per i test usa una porta alta come 4433, come in tutti gli esempi di questo tutorial, oppure concedi la capability CAP_NET_BIND_SERVICE al binario.
- kem_demo.py genera un AttributeError su encap_secret o decap_secret. I nomi dei metodi sono cambiati tra versioni di liboqs-python. Esegui
python3 -c "import oqs; help(oqs.KeyEncapsulation)"per vedere l'API esatta installata sulla tua macchina prima di correggere lo script.
Suggerimenti avanzati per la produzione
Una volta superato il laboratorio locale, alcuni accorgimenti separano un esperimento da una configurazione pronta per traffico reale. Il primo è la gestione dell'ordine dei gruppi: metti sempre il gruppo ibrido prima di quello classico nella configurazione del server, così i client che lo supportano lo useranno per default, mentre quelli più vecchi continuano a funzionare senza interruzioni. Il secondo riguarda il monitoraggio: aggiungi il controllo del passo 11 anche come health check periodico in produzione, non solo come gate della pipeline di deploy, perché un rollback di emergenza o un'immagine sbagliata promossa manualmente possono silenziosamente disattivare la protezione post-quantum.
Un quarto accorgimento riguarda la misurazione, non solo l'abilitazione. Prima di spingere il gruppo ibrido su tutto il traffico di produzione, misura la latenza dell'handshake con strumenti come curl --trace-time o uno script k6 dedicato, confrontando gruppo classico e ibrido sul tuo traffico reale, non su un benchmark generico trovato online. Alcuni team scelgono un rollout graduale, abilitando prima il gruppo ibrido su un sottoinsieme di endpoint meno critici, osservando metriche di errore e latenza per qualche settimana prima di estenderlo a tutto il resto dell'infrastruttura.
Il terzo accorgimento riguarda le firme digitali, da trattare separatamente dallo scambio di chiavi. Questo tutorial si concentra su ML-KEM per il key exchange perché è la parte già stabile e nativa in OpenSSL 3.5, ma la modernizzazione dei certificati verso ML-DSA o SLH-DSA è un progetto distinto, con tempistiche di adozione da parte delle Certification Authority ancora più lunghe. Pianifica le due migrazioni come progetti separati nel tuo roadmap, con owner e scadenze diverse.
Infine, segui l'evoluzione dello standard HQC. Il blog di OpenSSL Corporation ha già iniziato a parlare di scadenze concrete per la migrazione post-quantum, segno che il tema è passato dalla fase di curiosità tecnica a quella di pianificazione obbligatoria per chi gestisce infrastrutture critiche. Una classificazione accademica recente delle implementazioni esistenti, pubblicata su arXiv, può essere un buon punto di partenza se vuoi confrontare come diversi progetti open source hanno integrato gli stessi algoritmi prima di scegliere la tua libreria di riferimento.
Domande frequenti
Cos'è esattamente ML-KEM e in cosa differisce da RSA?
ML-KEM è un meccanismo di incapsulamento di chiave standardizzato nel FIPS 203, basato sul problema Module Learning With Errors sui reticoli. RSA si basa invece sulla difficoltà di fattorizzare numeri molto grandi. La differenza che conta è che un computer quantistico sufficientemente potente, eseguendo l'algoritmo di Shor, romperebbe RSA in tempo ragionevole, mentre non esiste ad oggi un algoritmo quantistico noto altrettanto efficace contro i problemi su reticoli usati da ML-KEM.
Devo migrare subito anche se gestisco un'infrastruttura piccola?
Dipende da quanto tempo i tuoi dati devono restare confidenziali. Se tratti dati con un valore che scade in pochi mesi, la fretta è minore. Se invece gestisci dati che devono restare segreti per anni, il rischio harvest now, decrypt later è già presente oggi, indipendentemente dalle dimensioni della tua infrastruttura.
OpenSSL 3.5 con ML-KEM è già sicuro da usare in produzione?
Gli standard FIPS 203, 204 e 205 sono finali e il NIST li descrive come pronti per l'implementazione. La configurazione ibrida, con ML-KEM insieme a un algoritmo classico, riduce ulteriormente il rischio, perché la sicurezza non dipende da un solo algoritmo appena standardizzato. Resta comunque buona prassi testare a fondo in staging prima di qualunque rollout su larga scala, come per ogni cambiamento alla propria infrastruttura TLS.
Lo scambio di chiavi ibrido rende le connessioni più lente?
Le chiavi pubbliche e i ciphertext di ML-KEM-768 sono più grandi di quelli di X25519, quindi l'handshake trasporta più byte. Non esiste però una cifra ufficiale unica valida per ogni scenario: l'impatto reale dipende da estensioni TLS attive, catena di certificati e rete, e va misurato caso per caso, come indicato nel passo 7.
Cosa cambia per i certificati TLS X.509 già esistenti?
Nulla di immediato. ML-KEM riguarda lo scambio di chiavi della sessione, non la firma del certificato che autentica il server. Puoi abilitare il gruppo ibrido lasciando inalterati i certificati firmati con ECDSA o RSA: la modernizzazione delle firme verso ML-DSA o SLH-DSA è un progetto separato, con tempi dettati anche dalle Certification Authority.
Che differenza c'è tra ML-KEM e ML-DSA?
ML-KEM (FIPS 203) serve allo scambio di chiavi: stabilisce un segreto condiviso. ML-DSA (FIPS 204) serve invece alle firme digitali: garantisce che un messaggio o un certificato provenga davvero da chi dichiara di averlo firmato. Entrambi si basano su reticoli, ma risolvono problemi diversi e vanno trattati come due migrazioni distinte.
HQC sostituirà ML-KEM in futuro?
Non è pensato come sostituto, ma come alternativa di riserva basata su una matematica diversa, i codici correttori d'errore invece dei reticoli. Il NIST l'ha selezionato nel marzo 2025 come quinto algoritmo di key establishment, con un draft dello standard atteso nel 2026 e la finalizzazione nel 2027. Serve a diversificare il rischio, non a rimpiazzare ML-KEM a breve termine.
Come posso verificare se un sito web sta già usando la crittografia post-quantum?
Usa il comando del passo 6 di questo tutorial puntandolo all'host che ti interessa invece che a 127.0.0.1, oppure controlla i dettagli della connessione TLS direttamente dagli strumenti per sviluppatori del tuo browser: i browser più recenti indicano il gruppo di scambio chiavi negoziato nella sezione dedicata alla sicurezza della connessione.
