Java vous fournit les briques post-quantiques avant de vous fournir une poignée de main TLS post-quantique. Pour une application Java côté serveur placée derrière un reverse proxy, le moyen le plus rapide d'obtenir un échange de clés hybride ML-KEM (Module-Lattice-Based Key Encapsulation Mechanism, normalisé dans NIST FIPS 203) consiste à mettre à jour le proxy, pas la JVM. Lorsque Java est le client TLS, l'échange de clés hybride dépend de la version du JDK et du fournisseur JSSE utilisé : la seule réponse fiable provient donc des notes de version du build que vous déployez réellement, confirmée par un test de poignée de main.
Déterminez d'abord de quel côté de la poignée de main vous êtes
Un échange de clés TLS est négocié par les deux piles qui réalisent la poignée de main, pas par le code applicatif. Trois cas couvrent presque tous les déploiements Java, et leurs réponses diffèrent.
- Trafic entrant terminé par un proxy. Un contrôleur d'ingress, un répartiteur de charge, un CDN ou une instance nginx, Apache, HAProxy ou Caddy réalise la poignée de main. La JVM ne voit jamais l'échange de clés. Mettre à jour le proxy suffit pour proposer des groupes hybrides aux navigateurs et aux clients d'API.
- Trafic entrant terminé par la JVM. Un listener Tomcat, Jetty, Undertow ou Netty embarqué, avec un keystore Java. Ici, la liste des groupes provient de l'implémentation TLS du JDK (JSSE), ou de la bibliothèque TLS native utilisée par le connecteur.
- Trafic sortant, Java en tant que client. Clients HTTP appelant des API partenaires, pilotes JDBC et de courtiers de messages, SDK de stockage objet, TLS mutuel entre services internes. Le côté Java propose la liste
supported_groupset le serveur distant en choisit un.
Ordonnez le travail en fonction du risque « récolter maintenant, déchiffrer plus tard » (HNDL) : un attaquant qui enregistre le trafic aujourd'hui pour le déchiffrer dans plusieurs années est mis en échec par l'échange de clés, pas par le certificat. C'est pourquoi l'établissement de clés ML-KEM passe en premier, la migration des signatures pouvant suivre. Le registre TLS de l'IANA recense les groupes hybrides en usage, dont X25519MLKEM768 (codepoint 0x11EC), SecP256r1MLKEM768 et SecP384r1MLKEM1024 (paramètres TLS de l'IANA), et la RFC 10024 spécifie l'accord de clés hybride post-quantique et traditionnel pour TLS 1.3 (RFC 10024).
Où en est le JDK aujourd'hui
Deux couches doivent être distinguées : les primitives cryptographiques exposées par la Java Cryptography Architecture (JCA), et la prise en charge des groupes hybrides dans JSSE.
Primitives : disponibles dans les versions actuelles
La JEP 452 a ajouté une API de mécanisme d'encapsulation de clés (KEM), javax.crypto.KEM, dans le JDK 21. Le JDK 24 a ajouté des implémentations de ML-KEM (JEP 496) et de ML-DSA (Module-Lattice-Based Digital Signature Algorithm, NIST FIPS 204) avec la JEP 497, accessibles via les API habituelles KeyPairGenerator, KEM et Signature, avec un nom d'algorithme pour chaque jeu de paramètres. Les fonctionnalités du JDK étant reconduites, les versions ultérieures les incluent. C'est ce dont vous avez besoin pour vos propres protocoles, l'encapsulation de clés, les formats de jetons et les bancs de test. Ce n'est pas, en soi, du TLS.
Groupes TLS hybrides : lisez les notes de version de votre JDK
Proposer un groupe hybride dans une poignée de main TLS 1.3 est un travail distinct au sein de JSSE : le groupe doit être enregistré, les partages de clés générés et analysés, et le secret partagé dérivé des deux composantes. Que le JDK que vous exécutez le fasse ou non, sous quels noms de groupes et avec ou sans activation par défaut, varie selon la version et selon le build de l'éditeur, car les distributions rétroportent de manière sélective. N'inférez pas la prise en charge TLS de la présence de ML-KEM dans la JCA, et ne vous fiez pas à un article rédigé pour un autre build. Consultez les notes de version de votre version exacte du JDK, puis vérifiez empiriquement avec le test de poignée de main ci-dessous.
| Couche | Ce qu'il faut vérifier | Où regarder |
|---|---|---|
| Primitives JCA | Génération de paires de clés ML-KEM et ML-DSA, encapsulation, vérification de signature | Notes de version du JDK, documentation des noms d'algorithmes standard |
| Groupes hybrides JSSE | Présence du groupe hybride dans le ClientHello ou le ServerHello | Notes de version du JDK, plus une poignée de main réelle avec journalisation de débogage |
| TLS natif derrière un connecteur | Version de la bibliothèque native utilisée par le connecteur (les groupes ML-KEM nécessitent OpenSSL 3.5 ou ultérieur dans les builds OpenSSL) | Arbre des dépendances, version de la bibliothèque native à l'exécution |
| Proxy ou ingress | Liste et ordre des groupes, présence maintenue du repli classique | Configuration du proxy et ses propres notes de version |
Vos options, par ordre d'effort
Terminer le TLS entrant sur un proxy
C'est l'option pragmatique par défaut pour Java côté serveur. Le proxy a besoin d'une bibliothèque TLS qui implémente les groupes ML-KEM : pour les builds OpenSSL, cela signifie OpenSSL 3.5 ou ultérieur. Configurez le groupe hybride en premier et conservez les groupes classiques après lui, afin que les clients sans prise en charge hybride puissent toujours se connecter, et validez en préproduction avant la production. Les directives pas à pas pour les serveurs courants figurent dans notre guide pour activer ML-KEM sur nginx, Apache, HAProxy et Caddy. Une précaution pratique : un partage de clé hybride est nettement plus volumineux qu'un partage de clé X25519, ce qui peut faire dépasser au ClientHello la taille d'un paquet. D'anciens équipements intermédiaires et des appliances réseau mal conçues gèrent parfois mal ce cas : testez donc depuis les réseaux que vos clients utilisent réellement.
Mettre à jour le JDK là où la JVM termine le TLS
Si un listener Java est directement exposé aux clients, ou si Java est le client d'une connexion qui vous importe, la solution propre consiste à exécuter une version du JDK dont JSSE propose le groupe hybride, puis à le confirmer sur le réseau. JSSE expose la propriété système documentée jdk.tls.namedGroups pour restreindre et ordonner les groupes proposés. Les noms acceptés dépendent de la version : reprenez-les de vos notes de version plutôt que de copier un exemple, et laissez toujours un groupe classique tel que X25519 dans la liste. N'imposez pas un unique groupe post-quantique en production.
Ajouter une bibliothèque fournisseur, ou faire passer le trafic sortant par une passerelle
Un fournisseur JCA ou JSSE tiers peut apporter des algorithmes et, dans certains cas, une pile TLS indépendante du JDK. Pesez ce choix avec soin : installer un fournisseur modifie le comportement de sécurité de toute la JVM, interagit avec le mode FIPS et avec la validation des chemins de certification, et devient une dépendance que vous devez maintenir à jour. Limitez le changement au SSLContext du client concerné lorsque la bibliothèque le permet, plutôt que de réordonner les fournisseurs globaux. Pour les appels sortants depuis des JVM anciennes qui ne peuvent pas être mises à jour, un proxy de sortie qui réalise la poignée de main est souvent plus simple et plus facile à auditer que la modification de chaque application. Notez également que les connecteurs reposant sur une bibliothèque TLS native (par exemple Netty avec netty-tcnative) suivent la version de cette bibliothèque, et non celle du JDK.
Inventorier l'usage cryptographique de Java avant toute modification
Tous les calendriers officiels commencent par la découverte, et les auditeurs demandent l'inventaire avant de demander la migration. Ces commandes en lecture seule vous donnent un premier aperçu ; adaptez les chemins à l'organisation de votre 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"
Ne vous limitez pas au TLS. Les applications Java signent aussi des JSON Web Tokens et des assertions SAML, vérifient des JAR signés, chiffrent des colonnes de bases de données et épinglent des ancres de confiance. Notez les algorithmes à clé publique vulnérables au quantique (RSA, ECDSA, EdDSA, ECDH, Diffie-Hellman sur corps finis et DSA sont tous affectés par l'algorithme de Shor, quelle que soit la taille de clé), l'endroit où chacun est utilisé, son responsable, et si l'algorithme est configurable sans modification du code. Une nomenclature cryptographique lisible par machine est un moyen pratique de tenir cette liste à jour : voir ce qu'est un CBOM et comment en produire un. Surveillez également les fichiers de politique de sécurité du JDK, car jdk.tls.disabledAlgorithms et jdk.certpath.disabledAlgorithms dans java.security déterminent déjà ce que vos JVM acceptent.
Tester ce que la poignée de main négocie réellement
Les déclarations de prise en charge ne valent rien sans un groupe effectivement négocié. Effectuez trois vérifications, dans cet ordre.
# 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"
L'étape 3 est décisive lorsque Java est client : la sortie de débogage montre les groupes présents dans le ClientHello et le groupe retenu pour l'échange de clés. Si le groupe hybride n'apparaît jamais, le build du JDK ne le propose pas, quoi que la documentation ait laissé entendre. Conservez cette sortie comme preuve, avec la chaîne de version du JDK et la date. Notre scanner gratuit couvre l'étape 1 depuis l'extérieur, y compris les versions de TLS, les suites de chiffrement et la chaîne de certificats ; ce qu'un résultat signifie et ne signifie pas est décrit dans notre page de méthodologie.
Ce que cela implique pour les audits
L'inventaire que vous venez de constituer est l'artefact demandé par la plupart des référentiels ; ce qui suit constitue une information et non un conseil juridique. L'exigence 12.3.3 de PCI DSS v4.0.1, obligatoire depuis le 31 mars 2025, demande un inventaire documenté des suites de chiffrement et des protocoles utilisés, revu au moins tous les 12 mois, assorti d'une stratégie face aux évolutions anticipées des vulnérabilités cryptographiques : voir notre page sur l'exigence 12.3.3 de PCI DSS. Au titre de DORA, l'Art. 6 du Commission Delegated Regulation (EU) 2024/1774 (règlement délégué (UE) 2024/1774 de la Commission) exige une politique de chiffrement et de contrôles cryptographiques prévoyant la mise à jour ou le changement des technologies cryptographiques au fil des progrès de la cryptanalyse, et l'Art. 7 exige une gestion des clés et un registre des certificats pour les actifs TIC soutenant des fonctions critiques ou importantes (EUR-Lex). Il s'agit d'une interprétation, et non du texte : dans un parc Java, la preuve concrète de l'Art. 6 est que vos services peuvent changer de groupes et d'algorithmes par configuration et par mise à jour du JDK ou du proxy, et non par une réécriture. Concernant le statut des algorithmes, le NIST a publié FIPS 203, 204 et 205 en tant que normes définitives le 13 août 2024 (FIPS 203), tandis que NIST IR 8547, qui propose de déprécier les algorithmes à clé publique offrant 112 bits de sécurité après 2030 et d'interdire les algorithmes à clé publique vulnérables au quantique après 2035, demeure un projet initial soumis à consultation publique (NIST IR 8547 ipd).
La prochaine étape concrète
Choisissez un service Java accessible depuis l'extérieur et analysez votre domaine avec PQC Status pour voir quel groupe il négocie aujourd'hui. Si la réponse est uniquement classique et qu'un proxy termine le TLS, mettez ce proxy à jour vers un build avec OpenSSL 3.5 ou ultérieur et placez le groupe hybride devant X25519 en préproduction. Si la JVM termine le TLS, ou si Java est le client d'une connexion transportant des secrets à longue durée de vie, consignez la version du JDK dans votre inventaire, lisez ses notes de version concernant l'échange de clés hybride, et capturez dans tous les cas un journal de poignée de main comme preuve. Relancez l'analyse après chaque changement, et conservez le repli classique tant que vos clients en ont besoin.