PQC Status
Guida

TLS post-quantum in Java: a che punto è il JDK e cosa fare ora

Il JDK include le primitive ML-KEM, ma il supporto ai gruppi TLS ibridi dipende dalla release in uso: come verificarlo, cosa modificare e come dimostrare che funziona.

· 9 min

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.

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.

LivelloCosa verificareDove guardare
Primitive JCAGenerazione di coppie di chiavi ML-KEM e ML-DSA, incapsulamento, verifica delle firmeRelease notes del JDK, documentazione dei nomi standard degli algoritmi
Gruppi ibridi JSSESe il gruppo ibrido compare nel ClientHello o nel ServerHelloRelease notes del JDK, più un handshake reale con logging di debug
TLS nativo dietro un connettoreVersione 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 ingressElenco e ordine dei gruppi, fallback classico ancora presenteConfigurazione 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.

Domande frequenti

Il JDK supporta nativamente il TLS ibrido post-quantum?

Il JDK include ML-KEM e ML-DSA come primitive crittografiche: la JEP 452 ha aggiunto l'API Key Encapsulation Mechanism nel JDK 21, e il JDK 24 ha aggiunto le implementazioni di ML-KEM (JEP 496) e ML-DSA (JEP 497). Lo scambio di chiavi ibrido all'interno dello stack TLS (JSSE) è un lavoro distinto, e la sua disponibilità dipende dalla release e dalla build del fornitore che distribuite. Consultate le release notes della vostra versione esatta del JDK, quindi verificate sul traffico effettivo con un handshake reale invece di darlo per scontato.

Devo aggiornare Java se la mia applicazione si trova dietro un reverse proxy?

Non per il traffico in ingresso. È il proxy a eseguire l'handshake, quindi il gruppo negoziato con browser e client API dipende dal proxy e dalla sua libreria TLS, che nelle build OpenSSL richiede OpenSSL 3.5 o successiva per i gruppi ML-KEM. Dovete comunque esaminare la JVM per le connessioni in uscita, in cui Java è il client TLS, e per qualsiasi listener che termini il TLS all'interno della JVM.

Come verifico quale gruppo di scambio di chiavi offre il mio client Java?

Avviate l'applicazione con la proprietà di sistema javax.net.debug impostata per registrare l'handshake, quindi esaminate l'estensione supported_groups nel ClientHello e il gruppo selezionato per lo scambio di chiavi. Se non compare alcun gruppo ibrido, quella build non ne offre. Salvate l'output insieme alla stringa di versione del JDK come evidenza per il vostro inventario crittografico.

Dovrei imporre solo un gruppo post-quantum in un'applicazione Java?

No. Mantenete un gruppo classico come X25519 dopo il gruppo ibrido, in modo che i peer privi di supporto ibrido possano comunque connettersi, e testate ogni modifica prima in staging. JSSE espone la proprietà documentata jdk.tls.namedGroups per limitare e ordinare i gruppi offerti, ma i nomi accettati dipendono dalla release del JDK, quindi ricavateli dalle vostre release notes e non da un esempio.