X25519MLKEM768 vs X25519, c’est le choix d’échange de clés que pose aujourd’hui chaque handshake TLS 1.3. X25519 seul est rapide et très compact, mais il ne résiste pas à un ordinateur quantique : le trafic enregistré aujourd’hui pourrait donc être déchiffré plus tard. X25519MLKEM768 exécute X25519 et ML-KEM-768 ensemble, si bien que la session reste confidentielle à moins que les deux ne soient cassés.
Vue d’ensemble
| X25519 | X25519MLKEM768 | |
|---|---|---|
| Groupe pris en charge (TLS) | x25519, 29 (0x001D) | X25519MLKEM768, 4588 (0x11EC), recommandé par l’IANA |
| Spécification | RFC 7748, RFC 9846 | RFC 10024 (2026), cadre général RFC 9954 |
| Composants | X25519 | ML-KEM-768 (FIPS 203) et X25519 |
| Key share du client | 32 octets | 1216 octets (clé d’encapsulation ML-KEM de 1184 octets + 32) |
| Key share du serveur | 32 octets | 1120 octets (chiffré ML-KEM de 1088 octets + 32) |
| Secret partagé fourni à la dérivation des clés (key schedule) | 32 octets | 64 octets (secret ML-KEM d’abord, puis X25519) |
| Résistance au quantique | Non | Oui, tant que ML-KEM-768 tient |
| Sécurité classique | X25519 | Au moins celle de X25519, même si ML-KEM était cassé |
| CPU par handshake, OpenSSL 3.6.5 | environ 52 000 opérations X25519 par seconde | environ 19 000–24 000 générations de clés, encapsulations ou décapsulations par seconde |
| ClientHello mesuré ci-dessous | 306 octets | 1484 octets |
| ServerHello mesuré ci-dessous | 122 octets | 1210 octets |
Débit mesuré avec openssl speed sur un cœur d’Apple M4 Max ; tailles de handshake issues de la capture ci-dessous.
Pourquoi l’hybride dès maintenant
L’échange de clés est exposé au scénario récolter maintenant, déchiffrer plus tard : un adversaire enregistre aujourd’hui des sessions chiffrées et les déchiffre dès qu’existe un ordinateur quantique cryptographiquement pertinent, en retrouvant les clés de session à partir de l’échange X25519 enregistré. La confidentialité persistante n’y change rien, car chaque échange enregistré peut être cassé séparément. Tout ce dont la confidentialité doit survivre à l’arrivée d’un tel ordinateur est déjà menacé : c’est pourquoi l’échange de clés a migré en premier, tandis que les signatures peuvent attendre plus longtemps.
La conception hybride couvre aussi le risque inverse. ML-KEM a été normalisé en août 2024 et reste jeune comparé à X25519 : un cassage mathématique ou une faille d’implémentation n’est donc pas impensable. X25519MLKEM768 concatène les deux secrets partagés dans la dérivation des clés TLS, si bien qu’un attaquant doit casser les deux. Pour ce groupe, la RFC 10024 place en premier la key share et le secret ML-KEM, contrairement aux hybrides sur courbes NIST (SecP256r1MLKEM768, 0x11EB, et SecP384r1MLKEM1024, 0x11ED), qui placent ECDH en premier.
Ce qui change sur le réseau
Le client envoie une key share de 1216 octets au lieu de 32 octets : un ClientHello typique passe ainsi d’environ 300 octets à environ 1,5 Ko et, avec toutes les autres extensions d’un navigateur, ne tient plus dans un seul paquet réseau. Le serveur répond avec une key share de 1120 octets. Un handshake réel avec Cloudflare, capturé avec OpenSSL 3.6.5, montre la différence :
echo | openssl s_client -connect cloudflare.com:443 -servername cloudflare.com -groups X25519MLKEM768 -brief 2>&1 | grep -E "Protocol|group"
echo | openssl s_client -connect cloudflare.com:443 -servername cloudflare.com -groups X25519MLKEM768 -msg 2>&1 | grep -E "ClientHello|ServerHello"
echo | openssl s_client -connect cloudflare.com:443 -servername cloudflare.com -groups X25519 -msg 2>&1 | grep -E "ClientHello|ServerHello"
Protocol version: TLSv1.3
Negotiated TLS1.3 group: X25519MLKEM768
>>> TLS 1.3, Handshake [length 05cc], ClientHello
<<< TLS 1.3, Handshake [length 04ba], ServerHello
>>> TLS 1.3, Handshake [length 0132], ClientHello
<<< TLS 1.3, Handshake [length 007a], ServerHello
Soit 1484 octets contre 306 pour le ClientHello, et 1210 contre 122 pour le ServerHello. Les ClientHello plus volumineux ont révélé des bugs dans des serveurs et des équipements intermédiaires qui supposaient que le message arrivait en une seule lecture TCP ou dans un seul paquet ; lorsque Chrome a activé par défaut les key shares hybrides Kyber dans sa version 124 (2024), plusieurs pare-feu et proxys ont dû être corrigés, une classe de problèmes documentée sur tldr.fail. Cloudflare et Google ont mesuré, du fait des octets supplémentaires, une hausse de quelques pour cent de la latence médiane du handshake, ce qui pèse bien moins que les allers-retours économisés par TLS 1.3 lui-même.
État du déploiement
- Navigateurs : Chrome et Edge proposent X25519MLKEM768 par défaut depuis la version 131 (novembre 2024), Firefox depuis la 132 sur ordinateur, Safari et la pile TLS système d’Apple depuis iOS 26 et macOS 26 (2025). La variante pré-standard
X25519Kyber768Draft00(0x6399) qu’ils utilisaient auparavant est obsolète. - Bibliothèques : OpenSSL 3.5 (avril 2025) envoie par défaut des key shares X25519MLKEM768 et X25519 ; Go 1.24 l’active par défaut dans
crypto/tls; le JDK 27 (septembre 2026, JEP 527) le propose en premier par défaut ; BoringSSL, rustls et NSS le prennent en charge. - Serveurs et CDN : Cloudflare, Google et d’autres grands fournisseurs le négocient avec les clients compatibles ; nginx, Apache et HAProxy en bénéficient via l’OpenSSL auquel ils sont liés.
- SSH : l’équivalent
mlkem768x25519-sha256est l’algorithme par défaut d’OpenSSH depuis la version 10.0 (RFC 10042).
Le test TLS post-quantique du navigateur montre ce que négocie votre propre navigateur.
Quand choisir l’un ou l’autre
- HTTPS public et API : proposez X25519MLKEM768 en premier et X25519 en second ; tout client moderne négocie l’hybride, et les anciens se replient sur X25519.
- Maillage de services interne et mTLS : hybride par défaut, en particulier pour les données soumises à de longues exigences de confidentialité.
- Déploiements orientés FIPS :
SecP256r1MLKEM768ouSecP384r1MLKEM1024si la liste approuvée de votre module exige des courbes NIST ; X25519MLKEM768 convient lorsque ML-KEM est le composant approuvé. - Liaisons contraintes où chaque paquet compte : mesurez d’abord ; l’hybride ajoute un paquet dans chaque sens, ce qui est généralement acceptable.
- X25519 seul : uniquement pour les pairs incapables d’utiliser l’hybride, jamais comme choix délibéré pour de nouveaux déploiements.
Notes de migration
- Mettez à jour la bibliothèque TLS (OpenSSL 3.5 ou ultérieur, Go 1.24 ou ultérieur, une version récente de BoringSSL ou de rustls) ; avec OpenSSL 3.5, les groupes par défaut incluent déjà l’hybride.
- Si vous définissez les groupes explicitement, ajoutez-le : par exemple
ssl_ecdh_curve X25519MLKEM768:X25519:prime256v1;dans nginx ouGroups = X25519MLKEM768:X25519:P-256dans un fichier de configuration OpenSSL. - Testez le chemin, pas seulement le serveur : les répartiteurs de charge, les WAF et les proxys qui inspectent TLS doivent gérer un ClientHello réparti sur plusieurs paquets et plusieurs lectures ; refaites les tests après leurs mises à jour.
- Vérifiez ce qui est négocié avec
openssl s_client -groups X25519MLKEM768ou les outils de développement du navigateur, et surveillez la part des handshakes hybrides. - Planifiez séparément le volet signature : l’hybride ne protège que la confidentialité ; les certificats et les signatures du handshake restent classiques jusqu’à l’arrivée des signatures post-quantiques dans la WebPKI.
Références
- RFC 10024, mécanismes hybrides PQ/T d’accord de clé pour TLS 1.3
- RFC 9954, échange de clés hybride dans TLS 1.3
- FIPS 203, ML-KEM
- RFC 7748, X25519
- Registre IANA des groupes pris en charge par TLS (TLS Supported Groups)
- Notes de version d’OpenSSL 3.5
- tldr.fail : bugs de fragmentation du ClientHello
- NIST IR 8547 ipd, §4.1.2 (établissement de clés)