Java mette a disposizione i mattoni post-quantum prima di offrire un handshake TLS post-quantum. Per un'applicazione Java lato server dietro un reverse proxy, la strada più rapida verso lo scambio di chiavi ibrido ML-KEM (Module-Lattice-Based Key Encapsulation Mechanism, standardizzato come NIST FIPS 203) consiste nell'aggiornare il proxy, non la JVM. Quando Java è il client TLS, lo scambio di chiavi ibrido dipende dalla release del JDK e dal provider JSSE in uso, quindi l'unica risposta affidabile proviene dalle release notes della build che distribuite effettivamente, confermata da un test di handshake.
Stabilite innanzitutto quale lato dell'handshake controllate
Uno scambio di chiavi TLS viene negoziato dai due stack che eseguono l'handshake, non dal codice applicativo. Tre casi coprono quasi tutti i deployment Java, e le risposte sono diverse.
- Traffico in ingresso terminato da un proxy. L'handshake viene eseguito da un ingress controller, un load balancer, una CDN o un'istanza di nginx, Apache, HAProxy o Caddy. La JVM non vede mai lo scambio di chiavi. Aggiornare il proxy è sufficiente per offrire gruppi ibridi a browser e client API.
- Traffico in ingresso terminato dalla JVM. Un listener Tomcat, Jetty, Undertow o Netty incorporato, con un keystore Java. In questo caso l'elenco dei gruppi proviene dall'implementazione TLS del JDK (JSSE), oppure dalla libreria TLS nativa utilizzata dal connettore.
- Traffico in uscita, Java come client. Client HTTP che chiamano API di partner, driver JDBC e di message broker, SDK di object storage, TLS mutuo tra servizi interni. Il lato Java propone l'elenco
supported_groupse il server remoto ne sceglie uno.
Definite le priorità in base allo scenario harvest now, decrypt later (HNDL): un attaccante che registra il traffico oggi e lo decifra anni dopo viene neutralizzato dallo scambio di chiavi, non dal certificato. Per questo l'instaurazione delle chiavi con ML-KEM viene per prima e la migrazione delle firme può seguire. Il registro TLS di IANA elenca i gruppi ibridi in uso, tra cui X25519MLKEM768 (codepoint 0x11EC), SecP256r1MLKEM768 e SecP384r1MLKEM1024 (parametri TLS IANA), e la RFC 10024 specifica l'accordo di chiavi ibrido post-quantum e tradizionale per TLS 1.3 (RFC 10024).
A che punto è oggi il JDK
Occorre tenere distinti due livelli: le primitive crittografiche esposte tramite la Java Cryptography Architecture (JCA) e il supporto ai gruppi ibridi all'interno di JSSE.
Primitive: disponibili nelle release attuali
La JEP 452 ha aggiunto nel JDK 21 un'API per i Key Encapsulation Mechanism (KEM), javax.crypto.KEM. Il JDK 24 ha aggiunto le implementazioni di ML-KEM (JEP 496) e di ML-DSA (Module-Lattice-Based Digital Signature Algorithm, NIST FIPS 204) con la JEP 497, accessibili tramite le consuete API KeyPairGenerator, KEM e Signature, con nomi di algoritmo per ciascun set di parametri. Poiché le funzionalità del JDK vengono mantenute nelle versioni successive, le release seguenti le includono. È ciò che serve per i vostri protocolli, il key wrapping, i formati di token e gli ambienti di test. Di per sé, però, non è TLS.
Gruppi TLS ibridi: leggete le release notes del vostro JDK
Offrire un gruppo ibrido in un handshake TLS 1.3 richiede un lavoro distinto all'interno di JSSE: il gruppo deve essere registrato, le key share generate e analizzate, e il segreto condiviso derivato da entrambe le componenti. Se il JDK in uso lo faccia, con quali nomi di gruppo e se la funzione sia abilitata per impostazione predefinita, varia a seconda della release e della build del fornitore, poiché le distribuzioni effettuano backport selettivi. Non deducete il supporto TLS dalla presenza di ML-KEM nella JCA e non fate affidamento su un articolo scritto per una build diversa. Consultate le release notes della vostra versione esatta del JDK, quindi verificate empiricamente con il test di handshake descritto più avanti.
| Livello | Cosa verificare | Dove guardare |
|---|---|---|
| Primitive JCA | Generazione di coppie di chiavi ML-KEM e ML-DSA, incapsulamento, verifica delle firme | Release notes del JDK, documentazione dei nomi standard degli algoritmi |
| Gruppi ibridi JSSE | Se il gruppo ibrido compare nel ClientHello o nel ServerHello | Release notes del JDK, più un handshake reale con logging di debug |
| TLS nativo dietro un connettore | Versione della libreria nativa usata dal connettore (i gruppi ML-KEM richiedono OpenSSL 3.5 o successiva nelle build OpenSSL) | Albero delle dipendenze, versione della libreria nativa a runtime |
| Proxy o ingress | Elenco e ordine dei gruppi, fallback classico ancora presente | Configurazione del proxy e relative release notes |
Le vostre opzioni, in ordine di impegno
Terminare il TLS in ingresso su un proxy
È la scelta predefinita pragmatica per Java lato server. Il proxy necessita di una libreria TLS che implementi i gruppi ML-KEM: nelle build OpenSSL ciò significa OpenSSL 3.5 o successiva. Configurate il gruppo ibrido per primo e mantenete i gruppi classici dopo di esso, in modo che i client privi di supporto ibrido possano comunque connettersi, e convalidate in staging prima della produzione. Le direttive passo per passo per i server più diffusi si trovano nella nostra guida per abilitare ML-KEM su nginx, Apache, HAProxy e Caddy. Un'avvertenza pratica: una key share ibrida è sensibilmente più grande di una key share X25519, il che può far sì che il ClientHello superi i limiti di un pacchetto. Middlebox datati e apparati di rete mal implementati talvolta gestiscono male questa situazione, quindi eseguite i test dalle reti effettivamente utilizzate dai vostri client.
Aggiornare il JDK dove la JVM termina il TLS
Se un listener Java è esposto direttamente ai client, o se Java è il client in una connessione rilevante per voi, la soluzione pulita è eseguire una release del JDK il cui JSSE offra il gruppo ibrido, e poi verificarlo sul traffico effettivo. JSSE espone la proprietà di sistema documentata jdk.tls.namedGroups per limitare e ordinare i gruppi offerti. I nomi accettati dipendono dalla release, quindi ricavateli dalle vostre release notes invece di copiare un esempio, e lasciate sempre nell'elenco un gruppo classico come X25519. Non vincolate la produzione a un unico gruppo post-quantum.
Aggiungere una libreria provider, o instradare il traffico in uscita tramite un gateway
Un provider JCA o JSSE di terze parti può fornire algoritmi e, in alcuni casi, uno stack TLS indipendente dal JDK. Valutatelo con attenzione: l'installazione di un provider modifica il comportamento di sicurezza dell'intera JVM, interagisce con la modalità FIPS e con la validazione del percorso di certificazione, e diventa una dipendenza da mantenere aggiornata. Quando la libreria lo consente, limitate la modifica al SSLContext del client specifico, invece di riordinare i provider globali. Per le chiamate in uscita da JVM legacy non aggiornabili, un proxy di egress che esegue l'handshake è spesso più semplice e più facile da sottoporre ad audit rispetto alla modifica di ogni applicazione. Notate inoltre che i connettori che utilizzano una libreria TLS nativa (ad esempio Netty con netty-tcnative) seguono la versione di tale libreria, non quella del JDK.
Inventariate l'uso della crittografia in Java prima di modificare qualsiasi cosa
Ogni roadmap ufficiale inizia con la fase di discovery, e gli auditor chiedono l'inventario prima di chiedere la migrazione. Questi comandi in sola lettura forniscono un primo quadro; adattate i percorsi alla struttura della vostra build.
# TLS and crypto entry points in application code
grep -rnE "SSLContext|SSLSocketFactory|HttpsURLConnection|TrustManager|KeyManagerFactory" --include="*.java" src/
# algorithm names and keystore formats hard coded in source or configuration
grep -rnE "RSA|ECDSA|SHA1|MD5|PKCS12|JKS" --include="*.java" --include="*.properties" --include="*.yml" .
# which TLS stack each service really uses
mvn -q dependency:tree | grep -Ei "netty|tcnative|conscrypt|bouncycastle|okhttp|httpclient"
./gradlew dependencies --configuration runtimeClasspath | grep -Ei "netty|tcnative|okhttp|httpclient"
# keys and certificates in a keystore, with their algorithms
keytool -list -v -keystore keystore.p12 -storetype PKCS12 | grep -E "Alias name|Signature algorithm name|Subject Public Key Algorithm"
Registrate più del solo TLS. Le applicazioni Java firmano anche JSON Web Token e asserzioni SAML, verificano JAR firmati, cifrano colonne di database e fissano trust anchor. Annotate gli algoritmi a chiave pubblica vulnerabili al quantum computing (RSA, ECDSA, EdDSA, ECDH, Diffie-Hellman su campi finiti e DSA sono tutti esposti all'algoritmo di Shor, qualunque sia la dimensione della chiave), dove ciascuno è utilizzato, chi ne è responsabile e se l'algoritmo è configurabile senza modificare il codice. Una distinta base crittografica leggibile dalle macchine è un modo pratico per mantenere aggiornato questo elenco: consultate che cos'è un CBOM e come produrlo. Tenete d'occhio anche i file di policy di sicurezza del JDK, poiché jdk.tls.disabledAlgorithms e jdk.certpath.disabledAlgorithms in java.security determinano già ciò che le vostre JVM accettano.
Verificate cosa negozia realmente l'handshake
Le dichiarazioni di supporto non valgono nulla senza un gruppo effettivamente negoziato. Eseguite tre controlli, in quest'ordine.
# 1. external view of the listener (OpenSSL 3.5 or later on the client side)
openssl s_client -connect api.example.com:443 -groups X25519MLKEM768 </dev/null 2>&1 | grep -i "Negotiated TLS1.3 group"
# 2. the classical fallback must still work
openssl s_client -connect api.example.com:443 -groups X25519 </dev/null 2>&1 | grep -i "Negotiated TLS1.3 group"
# 3. what the Java client offers, and what the peer selects
java -Djavax.net.debug=ssl:handshake -jar client.jar 2>&1 | grep -iE "supported_groups|named group|key_share"
Il passo 3 è quello decisivo per Java come client: l'output di debug mostra i gruppi nel ClientHello e il gruppo scelto per lo scambio di chiavi. Se il gruppo ibrido non compare mai, la build del JDK non lo offre, qualunque cosa suggerisse la documentazione. Conservate l'output come evidenza, insieme alla stringa di versione del JDK e alla data. Il nostro scanner gratuito copre il passo 1 dall'esterno, incluse le versioni TLS, le cipher suite e la catena di certificati; ciò che un risultato significa e non significa è descritto nella nostra pagina sulla metodologia.
Come tutto questo si riflette negli audit
L'inventario che avete appena costruito è l'artefatto richiesto dalla maggior parte dei framework, e quanto segue ha carattere informativo e non costituisce consulenza legale. Il requisito 12.3.3 di PCI DSS v4.0.1, obbligatorio dal 31 marzo 2025, richiede un inventario documentato delle cipher suite e dei protocolli in uso, riesaminato almeno ogni 12 mesi, con una strategia per far fronte ai cambiamenti previsti nelle vulnerabilità crittografiche: consultate la nostra pagina sul requisito 12.3.3 di PCI DSS. Nell'ambito di DORA, il Regolamento delegato della Commissione (EU) 2024/1774 Art. 6 richiede una policy sulla cifratura e sui controlli crittografici che preveda disposizioni per aggiornare o cambiare la tecnologia crittografica in funzione dell'evoluzione della crittoanalisi, e l'Art. 7 richiede la gestione delle chiavi e un registro dei certificati per gli asset ICT che supportano funzioni essenziali o importanti (EUR-Lex). Interpretazione, non testo normativo: in un parco applicativo Java, la prova pratica dell'Art. 6 è che i vostri servizi possano cambiare gruppi e algoritmi tramite configurazione e un aggiornamento del JDK o del proxy, non tramite una riscrittura. Per quanto riguarda lo stato degli algoritmi, il NIST ha pubblicato FIPS 203, 204 e 205 come standard definitivi il 13 agosto 2024 (FIPS 203), mentre NIST IR 8547, che propone di deprecare gli algoritmi a chiave pubblica con sicurezza a 112 bit dopo il 2030 e di vietare gli algoritmi a chiave pubblica vulnerabili al quantum computing dopo il 2035, rimane una bozza pubblica iniziale (NIST IR 8547 ipd).
Il prossimo passo concreto
Scegliete un servizio Java raggiungibile dall'esterno e analizzate il vostro dominio con PQC Status per vedere quale gruppo negozia oggi. Se la risposta è solo classico e un proxy termina il TLS, aggiornate quel proxy a una build con OpenSSL 3.5 o successiva e posizionate in staging il gruppo ibrido prima di X25519. Se è la JVM a terminare il TLS, o se Java è il client in una connessione che trasporta segreti di lunga durata, registrate la versione del JDK nel vostro inventario, leggetene le release notes relative allo scambio di chiavi ibrido e acquisite in ogni caso un log di handshake come evidenza. Ripetete la scansione dopo ogni modifica e mantenete il fallback classico finché i vostri client ne avranno bisogno.