Établir une clé : Diffie-Hellman, KEM et HPKE
- Accueil
- Cryptographie
- Établir une clé : Diffie-Hellman, KEM et HPKE
Établir une clé : Diffie-Hellman, KEM et HPKE
Section intitulée « Établir une clé : Diffie-Hellman, KEM et HPKE »Tout chiffrement symétrique performant suppose un secret partagé. Le problème n’est donc pas de chiffrer, mais d’établir une clé alors que le seul canal disponible est public, observable, et souvent manipulable. Trois outils empilés répondent à cette question : l’échange Diffie-Hellman, qui fabrique un secret commun par exponentiation dans un groupe ; les KEM (Key Encapsulation Mechanism, mécanisme d’encapsulation de clé), qui réduisent l’opération à deux fonctions, encapsuler et décapsuler ; et HPKE (Hybrid Public Key Encryption, chiffrement hybride à clé publique), qui fige l’assemblage KEM + KDF + AEAD jusqu’au chiffrement effectif des octets. Deux erreurs reviennent dans les implémentations : traiter le secret partagé comme une clé, et oublier que sans authentification, ce secret peut très bien être partagé avec l’attaquant.
Deux personnes veulent un mot de passe commun, mais elles ne peuvent que se parler à voix haute devant tout le monde. Elles utilisent un mélange de couleurs : chacune garde une couleur secrète, échange un mélange à voix haute, puis termine le mélange chez elle. Les deux obtiennent la même teinte finale, impossible à retrouver depuis les mélanges entendus.
→ Lire l’explication complète de la marmotte
Comment établir une clé partagée sans canal sécurisé, avec Diffie-Hellman ?
Section intitulée « Comment établir une clé partagée sans canal sécurisé, avec Diffie-Hellman ? »L’intuition de Diffie-Hellman, publiée en 1976, tient en une asymétrie de coût. On fixe publiquement un groupe cyclique (un ensemble d’éléments engendré par les puissances successives d’un même élément) et un générateur g. Alice tire un entier secret a et publie g^a. Bob tire b et publie g^b. Chacun élève la valeur reçue à sa puissance secrète : Alice calcule (g^b)^a, Bob calcule (g^a)^b, et les deux obtiennent g^(ab). Un observateur voit g, g^a et g^b, mais il ne sait pas calculer g^(ab) : c’est l’hypothèse CDH (Computational Diffie-Hellman, Diffie-Hellman calculatoire). Une hypothèse plus forte, DDH (Decisional Diffie-Hellman, Diffie-Hellman décisionnel), affirme qu’on ne sait même pas distinguer g^(ab) d’un élément aléatoire du groupe ; c’est elle qu’on utilise en pratique pour prouver l’indistinguabilité des clés dérivées.
Le point crucial est que le secret n’est jamais transmis : il est construit des deux côtés à partir d’éléments dont un seul est public. Aucun message ne contient la clé, donc aucune interception passive ne la révèle, même a posteriori. C’est l’origine de la forward secrecy (confidentialité persistante) : si les deux parties jettent a et b après l’échange, la compromission ultérieure de leurs clés d’identité à long terme ne permet pas de recalculer g^(ab) et donc pas de déchiffrer les sessions enregistrées. Cette propriété explique pourquoi TLS (Transport Layer Security) 1.3 a supprimé les suites RSA (Rivest-Shamir-Adleman) à transport de clé, dans lesquelles la clé de session était chiffrée sous la clé publique durable du serveur et redevenait donc lisible dès que cette clé fuitait.
La faille béante de la version sans authentification est l’attaque de l’homme du milieu, ou MITM (Man-In-The-Middle). Une machine placée sur le chemin remplace g^a par g^m vers Bob et g^b par g^m' vers Alice. Elle négocie deux secrets distincts, un avec chacun, déchiffre et rechiffre à la volée. Rien dans le calcul mathématique n’est cassé : c’est l’absence de lien entre les valeurs publiques et les identités qui l’est. Un Diffie-Hellman anonyme garantit la confidentialité contre un écouteur passif et absolument rien contre un attaquant actif. Il faut donc lier les valeurs échangées à une identité vérifiable, ce qui prend trois formes en pratique : signature du transcript par une clé certifiée (le choix de TLS 1.3), inclusion d’une clé statique dans le calcul (Diffie-Hellman authentifié, MQV, X3DH de Signal), ou dérivation à partir d’un mot de passe faible via un protocole PAKE (Password-Authenticated Key Exchange) comme OPAQUE, qui résiste au dictionnaire hors ligne contrairement aux vieux EKE (Encrypted Key Exchange).
Le choix du groupe est l’autre source de désastres. En Diffie-Hellman à corps fini, les groupes de moins de 2048 bits sont hors jeu : l’attaque Logjam (2015) a montré qu’un adversaire étatique pouvait précalculer un groupe de 1024 bits et que des groupes de 512 bits, encore acceptés par des serveurs via des suites d’export, tombaient en minutes. Le précalcul est amorti sur tous les échanges partageant le même module, ce qui rend les groupes « standard » plus attractifs pour l’attaquant, non moins. Sur courbes elliptiques, une courbe de 256 bits comme X25519 offre environ 128 bits de sécurité et coûte quelques dizaines de microsecondes par opération, avec en prime une conception qui neutralise trois classes de bugs : les vérifications de point oubliées, les sous-groupes de petit ordre exploitables et les branches conditionnelles dépendant du secret. En pratique : X25519 par défaut, P-256 si la conformité l’exige, jamais de groupe DH à corps fini négocié dynamiquement.
Pourquoi ne jamais utiliser le secret partagé tel quel, et à quoi sert un KEM ?
Section intitulée « Pourquoi ne jamais utiliser le secret partagé tel quel, et à quoi sert un KEM ? »La sortie brute d’un Diffie-Hellman n’est pas une chaîne uniformément aléatoire. Pour un groupe à corps fini, c’est un entier dans [1, p-1] avec une structure algébrique et des bits de poids fort biaisés ; sur courbe de Montgomery, c’est une coordonnée x dont certains bits sont corrélés. Prendre ces octets comme clé AES (Advanced Encryption Standard) est une faute : on injecte du biais dans le keystream et on perd la garantie d’indistinguabilité que DDH ne fournit que modulo extraction. La règle est donc absolue : passer par une KDF (Key Derivation Function, fonction de dérivation de clé), typiquement HKDF (HMAC-based Key Derivation Function) en deux étapes, extract puis expand.
L’étape extract condense le secret et un sel en une clé pseudo-aléatoire uniforme ; l’étape expand produit autant d’octets qu’on veut, séparés par un label de contexte. Ce label n’est pas décoratif : il assure la séparation de domaine, c’est-à-dire l’indépendance statistique entre deux clés issues du même secret. Deux clés dérivées avec les labels "client write" et "server write" ne se déduisent pas l’une de l’autre, ce qui évite les attaques de réflexion où un message chiffré dans un sens est rejoué dans l’autre. Le contexte doit aussi inclure le transcript (la suite exacte des messages échangés), ou au moins les valeurs publiques et les identités : c’est ce qui empêche un attaquant de recycler un secret négocié dans une session vers une autre. Un échange dont la clé finale ne dépend pas du transcript complet est vulnérable aux attaques de renégociation et de confusion d’identité, comme l’a montré la famille Triple Handshake.
Le KEM est l’abstraction qui range tout cela derrière trois fonctions. KeyGen produit une paire (sk, pk). Encap(pk) produit un couple (shared_secret, enc) où enc est un encapsulé à transmettre. Decap(sk, enc) recalcule shared_secret. Contrairement au chiffrement asymétrique général, un KEM ne chiffre pas un message choisi : il fabrique une clé aléatoire et son enveloppe. Cette restriction est ce qui rend l’interface saine : pas de padding à malmener, pas d’oracle sur un plaintext structuré, donc pas de Bleichenbacher. Un DH éphémère-statique se réécrit en KEM (DHKEM) au prix d’un simple renommage des rôles : enc est la valeur publique éphémère, shared_secret est le résultat du DH passé dans une KDF avec les deux clés publiques. Les KEM post-quantiques comme ML-KEM (anciennement Kyber, normalisé FIPS 203 en 2024) exposent la même interface sans reposer sur un groupe, ce qui permet de les substituer ou de les combiner en hybride sans réécrire le protocole appelant.
Attention à une propriété non triviale : la robustesse de liaison. Un KEM mal conçu peut permettre de fabriquer un encapsulé qui se décapsule vers le même secret sous deux clés privées différentes ; l’expéditeur croit alors parler à un destinataire pendant qu’un autre lit le trafic. D’où l’inclusion systématique de enc et de pk dans le calcul du secret, exactement ce que fait DHKEM avec son kem_context.
Comment HPKE assemble KEM, KDF et AEAD en une brique réutilisable ?
Section intitulée « Comment HPKE assemble KEM, KDF et AEAD en une brique réutilisable ? »HPKE, normalisé par le RFC 9180 en 2022, répond à un constat : chaque protocole réinventait le même montage « je génère une clé éphémère, je fais un DH, je dérive, je chiffre » avec ses propres bugs. HPKE fixe la recette. On choisit une suite composée d’un KEM, d’une KDF et d’un AEAD (Authenticated Encryption with Associated Data, chiffrement authentifié avec données associées) ; l’identifiant de suite est lui-même intégré dans la dérivation, ce qui empêche la confusion entre algorithmes.
Le flux tient en quatre étapes. L’expéditeur appelle SetupBaseS(pkR, info) : le KEM produit (shared_secret, enc), la KDF combine shared_secret, l’identifiant de suite, un mode et un haché de info pour produire une clé AEAD, un nonce de base et un exporter_secret. L’expéditeur envoie enc puis des messages scellés. Le destinataire appelle SetupBaseR(skR, enc, info) et reconstitue le même contexte. Le nonce de chaque message est le nonce de base XORé avec un compteur de séquence : c’est ce qui garantit l’unicité sans coordination, à condition de ne jamais réutiliser un contexte pour deux flux indépendants.
Un exemple chiffré rend les tailles concrètes. Avec la suite DHKEM(X25519, HKDF-SHA256) / HKDF-SHA256 / ChaCha20-Poly1305, un message de 100 octets scellé en mode base donne : enc de 32 octets (la clé publique éphémère), un chiffré de 100 octets, une étiquette Poly1305 de 16 octets. Soit 148 octets sur le fil, dont 48 de surcoût pour le premier message et 16 seulement pour les suivants, puisque enc n’est transmis qu’une fois. En interne, shared_secret fait 32 octets, la clé AEAD 32 octets, le base_nonce 12 octets, le compteur de séquence 12 octets également. Le message numéro 3 utilise donc le nonce base_nonce XOR 0x000000000000000000000003.
Quatre modes existent. base n’authentifie que le destinataire. psk ajoute un secret pré-partagé, injecté dans la dérivation, qui authentifie l’expéditeur sous réserve que le PSK (Pre-Shared Key, clé pré-partagée) reste secret. auth fait intervenir la clé statique de l’expéditeur dans le KEM, ce qui donne une authentification implicite : seul le possesseur de skS a pu produire ce secret. auth_psk combine les deux. À noter que l’authentification de auth est implicite et non transférable : le destinataire est convaincu, mais il ne peut pas le prouver à un tiers, contrairement à une signature. C’est parfois un avantage (déni plausible), parfois un défaut (non-répudiation impossible).
Le paramètre info est l’endroit où lier le chiffré à son usage applicatif : nom de service, version de protocole, identifiant de ressource. Deux contextes construits avec des info différents produisent des clés indépendantes. L’oublier, c’est autoriser un chiffré destiné à un endpoint à être accepté par un autre. Concrètement, un jeton scellé avec info = "billing-api v2" échoue au déchiffrement sur un service qui attend info = "admin-api v2" : la clé AEAD dérivée diffère, la vérification de l’étiquette Poly1305 rate, Open renvoie une erreur. Le champ aad de chaque Seal joue le même rôle au niveau du message : en-têtes, numéro de version, tout ce qui doit être authentifié sans être chiffré.
Le destinataire refait le même calcul avec sa clé privée durable et enc, et obtient bit pour bit les mêmes clés. Un montage fait à la main, qui se contenterait d’enchaîner l’échange de clés et la dérivation, oublierait ce que HPKE fait en plus : inclure enc et pkR dans le calcul du secret, ce qui garantit la robustesse de liaison. En production, on utilise une bibliothèque HPKE conforme, jamais un montage artisanal.
HPKE est aujourd’hui la brique de plusieurs déploiements massifs : ECH (Encrypted Client Hello) chiffre le nom de domaine dans la poignée de main TLS, Oblivious DoH (DNS over HTTPS) découple requête et identité du client, Message Layer Security s’en sert pour les mises à jour de clé, et les Privacy Pass y recourent pour les jetons anonymes. La transition post-quantique s’appuie sur des KEM hybrides du type X25519+ML-KEM-768, où le secret est la concaténation des deux secrets passée dans la KDF : casser l’un ne suffit pas.
Quels pièges reviennent systématiquement quand on établit une clé en production ?
Section intitulée « Quels pièges reviennent systématiquement quand on établit une clé en production ? »Le premier reste l’absence d’authentification. Un échange X25519 correctement implémenté ne vaut rien si la clé publique reçue n’est reliée à personne. Il faut un certificat vérifié, un pinning, un TOFU (Trust On First Use) assumé, ou un PSK, mais quelque chose. Le deuxième est la réutilisation d’un éphémère : réutiliser a sur plusieurs sessions détruit la forward secrecy et, sans validation de la clé publique reçue, ouvre la porte aux attaques par sous-groupe de petit ordre ou par courbe invalide qui extraient le secret bit par bit. Le troisième est la réutilisation d’un nonce AEAD, souvent causée par un contexte HPKE partagé entre deux threads sans compteur atomique : avec GCM ou Poly1305, cela livre le keystream et la clé d’authentification.
Vient ensuite la mauvaise validation des entrées. Sur P-256, il faut vérifier que le point reçu satisfait l’équation de la courbe et appartient au bon sous-groupe. Sur X25519, il faut rejeter un secret partagé nul, signe d’un point d’ordre faible envoyé exprès. Enfin, la dérivation sans contexte : deux usages partageant la même clé sans label distinct finissent par se contaminer, un chiffré de l’un devenant déchiffrable par l’autre.
Un KEM remplace-t-il Diffie-Hellman ? Non, il l’abstrait. DHKEM est un Diffie-Hellman éphémère-statique exposé derrière l’interface KEM. L’intérêt de l’abstraction est de pouvoir remplacer le mécanisme sous-jacent, par un KEM à réseaux euclidiens comme ML-KEM ou par une combinaison hybride, sans toucher au protocole appelant.
HPKE fournit-il la forward secrecy ?
Côté expéditeur oui, puisque sa clé est éphémère et jetée. Côté destinataire non : la clé statique skR permet de décapsuler tout chiffré passé. Pour une forward secrecy complète, il faut des clés destinataires à durée de vie courte, ou un échange interactif à double éphémère comme celui de TLS 1.3.
Pourquoi HKDF plutôt qu’un simple SHA-256 du secret ? Un haché brut fonctionne parfois mais ne donne ni sel, ni séparation de domaine, ni longueur de sortie variable, ni structure prouvée pour l’extraction d’entropie non uniforme. HKDF sépare explicitement extraction et expansion, ce qui permet de dériver plusieurs clés indépendantes du même secret avec des labels distincts, indispensable pour les clés directionnelles.
Faut-il déjà passer au post-quantique ? Pour tout trafic dont la confidentialité doit tenir plus de dix ans, oui : un adversaire peut enregistrer aujourd’hui et déchiffrer plus tard. Le mode raisonnable est l’hybride X25519+ML-KEM-768, déjà déployé par les grands navigateurs, qui ne dégrade pas la sécurité classique en cas de faille dans le schéma récent.
Conclusion
Section intitulée « Conclusion »Établir une clé, c’est enchaîner trois opérations qu’il ne faut jamais confondre : produire un secret commun, l’authentifier, puis le transformer en clés utilisables. Diffie-Hellman règle le premier point depuis 1976 avec deux exponentiations, mais ne dit rien du deuxième : sans lien vers une identité, un MITM négocie deux secrets et lit tout. Le KEM nettoie l’interface en Encap/Decap et prépare la substitution par ML-KEM. HPKE fige la recette complète, info et compteur de nonce compris, et supprime la classe d’erreurs qui venait du montage manuel. Trois réflexes suffisent à couvrir l’essentiel : authentifier toute clé publique reçue, ne jamais utiliser un secret brut sans KDF, ne jamais rejouer un nonce.
🐝 Ce qui arrive si on s’en passe
Section intitulée « 🐝 Ce qui arrive si on s’en passe »Sans établissement de clé digne de ce nom, il reste deux replis habituels, et tous deux se paient. Le premier est la clé symétrique fixe, distribuée une fois et jamais renouvelée : sa fuite ouvre tout le trafic, passé comme futur, et sa rotation impose de toucher chaque équipement au même moment. Le second est le transport de clé chiffré sous une clé publique durable, avec son rembourrage à malmener : c’est exactement la brèche « la question qui rend le module bavard », consignée dans la page sur l’attaque de Bleichenbacher, où un module interrogé avec patience finit par livrer le secret. Dans les deux cas, l’enquête après incident ne peut plus borner l’exposition à une session : tout ce qui a transité est présumé lu.
🦫 Explication de la marmotte 🍫
Section intitulée « 🦫 Explication de la marmotte 🍫 »Deux ordinateurs veulent se parler en secret, mais tout ce qu’ils s’envoient passe devant tout le monde. Ils utilisent une astuce mathématique : chacun choisit un nombre secret, en fabrique une version publique impossible à inverser, et l’envoie. En combinant sa version secrète avec la version publique de l’autre, chacun obtient le même résultat final. Un espion qui a tout entendu ne peut pas le retrouver : le calcul est facile dans un sens, hors de portée dans l’autre.
Mais il y a un piège. Si quelqu’un se place au milieu et échange les messages, il peut se faire passer pour chacun des deux. Il faut donc une preuve d’identité : une signature, un certificat, ou un mot de passe déjà connu des deux côtés.
Ensuite, le résultat commun n’est pas directement utilisable comme clé : ses chiffres ne sont pas assez « mélangés », certains reviennent plus souvent que d’autres. On le passe dans une machine à brasser qui produit une vraie clé, plus une étiquette indiquant l’usage précis. Deux étiquettes différentes donnent deux clés indépendantes.
Enfin, plutôt que de refaire ce montage à la main chaque fois, une norme appelée chiffrement hybride à clé publique fixe la recette entière : fabriquer le secret, le brasser, chiffrer les messages avec un compteur qui interdit de réutiliser deux fois la même protection.
À lire aussi
- Courbes elliptiques : compacité, validation et piègesRendre les courbes elliptiques utilisables sans excès d’algèbre, en insistant sur le choix de courbe, les encodages et les erreurs de validation.
- Les problèmes difficiles qui rendent la clé publique possiblePrésenter les objets mathématiques nécessaires sans transformer le site en manuel abstrait, et relier chaque difficulté à une famille de primitives.
- Intégrer la cryptographie post-quantique dans TLSMigration progressive de TLS vers les mécanismes post-quantiques hybrides, face à la menace store now, decrypt later.
- Comprendre TLS : mécanismes, garanties et limitesComprendre TLS : mécanismes de la négociation, garanties de confidentialité et d'authentification, forward secrecy et limites du protocole.
Pages voisines
La citent
- Courbes elliptiques : compacité, validation et pièges
- RSA : trappe, padding et usages restreints
- Du chiffre manuel au chiffrement moderne
- Ce que le bout en bout laisse voir
- JWE : chiffrer un jeton JSON sans se tromper
- La poignée de main TLS 1.3 en une page
- Vérifier un protocole cryptographique avec Tamarin ou ProVerif
Établir une clé : Diffie-Hellman, KEM et HPKE
Elle cite
: les deux pages se citent l’une l’autre.
