02 / 04 Le nonce, le détail qui fait tout s'effondrer
  1. ← Chiffrement authentifié : pourquoi chiffrer ne suffit jamais
  2. 01 Chiffrer ne suffit pas
  3. 02 Le nonce, le détail qui fait tout s'effondrer
  4. 03 Lier le chiffré à son contexte
  5. 04 Concevoir l'échec
Chiffrement authentifié : pourquoi chiffrer ne suffit jamais · 02 / 04

Le nonce, le détail qui fait tout s'effondrer

Unicité vitale, aléatoire contre compteur, borne d'anniversaire et temps constant : pourquoi le nombre le moins secret du système est aussi le plus dangereux.

Au chapitre précédent, tu as vu que l’AEAD garantit confidentialité et intégrité en une seule opération, à condition que ses paramètres soient utilisés correctement. Le nonce fait partie de ces paramètres. Et sa contrainte d’usage est absolue.

En 2016, des chercheurs ont publié la “Forbidden attack” contre AES-GCM. L’attaque ne casse pas l’algorithme. Elle exploite une seule erreur d’utilisation : réutiliser le même nonce avec la même clé. Résultat : non seulement les deux messages se retrouvent partiellement exposés, mais la clé d’authentification interne (la clé GHASH, dérivée du polynôme de hachage de GCM) peut être reconstruite par l’adversaire. Quand la clé GHASH est connue, l’intégrité s’effondre entièrement : l’adversaire peut forger des tags valides pour n’importe quel message.

À la fin de ce chapitre, tu sauras expliquer pourquoi l’unicité du nonce est une contrainte de sécurité et non une convention, montrer ce que la réutilisation révèle via l’intuition du “two-time pad”, distinguer les stratégies aléatoire et compteur pour la génération de nonces, et comprendre pourquoi la comparaison de tags doit s’effectuer en temps constant.

Le nonce

Le nonce Nonce Valeur utilisée une seule fois avec une clé donnée. C'est l'unicité qui importe, non le secret : réutiliser un nonce avec la même clé brise complètement le schéma. Un nonce aléatoire de 192 bits (XChaCha20) offre une probabilité de collision négligeable, tandis qu'un compteur de 96 bits (AES-GCM, ChaCha20-Poly1305) exige une gestion rigoureuse pour ne jamais dépasser 2^32 messages par clé. Source : RFC 8439 (contraction de “number used once”) est une valeur transmise en clair avec chaque message chiffré. Son rôle est précis : garantir que deux chiffrements du même texte clair avec la même clé produisent des chiffrés différents.

Ce qui compte n’est pas sa confidentialité, mais son unicité. Un nonce peut être lu par n’importe qui sur le réseau sans que cela affecte la sécurité. En revanche, utiliser deux fois le même nonce avec la même clé, même pour deux messages distincts, brise des garanties fondamentales.

La taille et la stratégie de génération varient selon la primitive. AES-GCM utilise un nonce de 96 bits. XChaCha20-Poly1305 utilise un nonce de 192 bits. Ces différences ont des conséquences concrètes sur la façon dont on génère les nonces, comme on le verra plus loin.

Réutilisation : la catastrophe

L’intuition du two-time pad

Pour comprendre pourquoi la réutilisation du nonce est catastrophique, il suffit de regarder ce que fait un chiffrement à flot sous le capot.

Un chiffrement à flot (comme le flux de clé dans ChaCha20 ou le mode CTR sous AES-GCM) génère un flux pseudo-aléatoire KsK_s depuis la clé kk et le nonce NN. Le texte clair PP est XORé avec ce flux :

C=PKs(k,N)C = P \oplus K_s(k, N)

Si deux messages P1P_1 et P2P_2 sont chiffrés avec le même kk et le même NN, leurs chiffrés sont :

C1=P1KsetC2=P2KsC_1 = P_1 \oplus K_s \quad \text{et} \quad C_2 = P_2 \oplus K_s

Un adversaire qui dispose des deux chiffrés calcule :

C1C2=(P1Ks)(P2Ks)=P1P2C_1 \oplus C_2 = (P_1 \oplus K_s) \oplus (P_2 \oplus K_s) = P_1 \oplus P_2

Le flux de clé KsK_s s’annule. L’adversaire obtient directement le XOR des deux textes clairs. Si l’un des deux messages est connu (ou devinable, comme un en-tête de protocole fixe), l’autre est immédiatement récupérable. C’est ce qu’on appelle le “two-time pad”, par analogie avec le one-time pad dont il rompt l’invariant fondamental.

Le composant ci-dessous illustre cette mécanique. Édite les deux messages et observe comment le XOR des chiffrés révèle directement la combinaison des textes clairs. Modifie le premier message pour qu’il ressemble à un en-tête de protocole connu, et regarde ce que le champ “récupéré” affiche pour le second.

C1 XOR C2 (observé par l'adversaire)
00 00 00 00 00 00 14 10 04 05 07 01 0e 1b 11
Message 2 récupéré (connaissant le message 1)
auth: adminroot

La Forbidden attack : quand l’intégrité s’effondre aussi

La fuite des textes clairs n’est que la première conséquence. Dans AES-GCM, le tag d’authentification est calculé via une fonction polynomiale (GHASH) paramétrée par une clé interne HH, dérivée de la clé principale. Si deux messages chiffrés avec le même nonce et la même clé sont observés, un adversaire peut construire un système d’équations sur HH et le résoudre. Une fois HH connue, il peut forger un tag valide pour n’importe quel chiffré de son choix.

La réutilisation du nonce ne dégrade pas la sécurité d’AES-GCM : elle l’annule.

Réutilisation du nonce : le flux de clé s'annule (two-time pad), et dans AES-GCM, la clé GHASH peut être reconstituée, permettant la forge de tags.

Aléatoire contre compteur

Deux stratégies principales existent pour générer des nonces uniques. Elles ont des profils de risque très différents.

Nonce aléatoire

Tirer un nonce uniformément au hasard dans un espace suffisamment grand rend les collisions négligeables. XChaCha20-Poly1305 utilise un nonce de 192 bits : il faudrait de l’ordre de 2642^{64} messages chiffrés sous la même clé pour que la probabilité de collision atteigne seulement 2652^{-65}, un risque négligeable à toute échelle réelle. On peut générer ces nonces avec un générateur cryptographique sûr sans aucune coordination entre les parties.

AES-GCM avec son nonce de 96 bits est plus contraignant. La borne d’anniversaire nous dit que la probabilité de collision croît approximativement comme le carré du nombre de nonces générés divisé par la taille de l’espace : après 2322^{32} messages (environ quatre milliards), la probabilité de collision avec un nonce aléatoire de 96 bits dépasse 2332^{-33}, ce qui devient préoccupant dans des systèmes à haut débit. La recommandation NIST limite l’utilisation d’une même clé AES-GCM à 2322^{32} messages avec des nonces aléatoires.

Nonce compteur

Un compteur monotone garantit l’unicité sans limite probabiliste : chaque valeur est distincte par construction. C’est la stratégie recommandée pour AES-GCM dans des systèmes déterministes (un seul producteur, une seule clé, un état persistant).

La fragilité est opérationnelle. Un compteur doit être :

  • Persistant : un redémarrage ne doit pas remettre le compteur à zéro. Si la valeur n’est pas sauvegardée en stockage durable, le nonce 0 sera réutilisé après chaque redémarrage.
  • Unique par instance : dans un système distribué, deux nœuds avec la même clé qui maintiennent chacun leur propre compteur vont inévitablement produire les mêmes valeurs. Il faut soit une coordination centrale, soit inclure un identifiant unique du nœud dans le nonce.
  • Non recyclable : une clé dont le compteur a atteint sa limite ne peut plus être utilisée. Il faut prévoir la rotation des clés.

La règle de conception qui en découle : une garantie qui repose sur une condition d’usage (l’unicité du nonce) doit être rendue impossible à violer par construction, pas confiée à la discipline humaine. Préférer des primitives à grand nonce (XChaCha20-Poly1305) quand la gestion d’état est difficile. Quand un compteur est nécessaire, le rendre inaccessible à la couche applicative et le faire gérer par la couche cryptographique.

Temps constant

La vérification du tag à l’ouverture doit s’effectuer en temps constant Temps constant Propriété d'une implémentation dont la durée d'exécution ne dépend pas des valeurs secrètes traitées, éliminant les canaux auxiliaires temporels. Elle est indispensable pour la comparaison de tags d'authentification et pour les opérations cryptographiques sensibles. ChaCha20-Poly1305 est naturellement en temps constant en logiciel, tandis qu'AES nécessite des instructions matérielles (AES-NI) pour atteindre cette propriété. : le temps d’exécution ne doit pas dépendre des valeurs comparées.

Pourquoi ? Parce qu’une comparaison naïve (octet par octet, retour dès la première différence) crée un canal caché temporel. Un adversaire qui peut mesurer le temps de réponse d’un serveur obtient une information : si le rejet arrive plus vite, les premiers octets du tag sont incorrects. Si le rejet prend un peu plus de temps, les premiers octets correspondent. En répétant suffisamment de tentatives, il peut reconstruire le tag valide octet par octet, sans jamais connaître la clé.

La défense est simple à énoncer : comparer les deux tags via un XOR de tous les octets, puis vérifier que le résultat cumulé est nul, sans branchement conditionnel anticipé.

La question du temps constant s’étend aussi à la primitive elle-même. ChaCha20 est conçu pour ne dépendre que d’additions, de rotations et de XOR, des opérations dont le temps d’exécution ne varie pas avec les données. AES en logiciel pur (sans instruction AES-NI) utilise des tables de substitution (S-box) accédées en mémoire : le cache processeur peut trahir quelles entrées ont été accédées, créant une fuite par canal auxiliaire de cache. Avec AES-NI, les instructions matérielles sont en temps constant par construction.

Comparaison naïve : le temps de rejet varie selon la position du premier octet différent, créant un canal temporel. Comparaison en temps constant : tous les octets sont traités avant tout branchement.

Choisir une primitive

Le choix entre AES-GCM et (X)ChaCha20-Poly1305 dépend du contexte de déploiement, pas d’une supériorité absolue de l’un sur l’autre.

AES-GCM est à privilégier quand l’environnement dispose d’AES-NI (serveurs x86-64, ARM Cortex-A avec ARMv8-A crypto). Les performances sont excellentes et le temps constant est garanti par le matériel. La contrainte principale est la gestion du nonce de 96 bits : un compteur bien géré est nécessaire dans les systèmes à fort débit ou distribués.

ChaCha20-Poly1305 est à privilégier dans les environnements sans accélération matérielle AES : mobiles anciens, microcontrôleurs, WASM, JavaScript natif. Les performances sont comparables ou meilleures, et le temps constant est assuré par construction algorithmique, sans dépendre du matériel. Le nonce de 192 bits de XChaCha20 simplifie considérablement la gestion en permettant la génération aléatoire sans limite pratique.

La agilité cryptographique Crypto-agilité Capacité d'un format ou d'un protocole à migrer vers de nouveaux primitifs cryptographiques sans casser les données existantes. Elle s'implémente typiquement par un octet de version en tête du chiffré, permettant de décoder les anciens enregistrements et de chiffrer les nouveaux avec l'algorithme courant. Elle est essentielle pour préparer une migration post-quantique. recommande de ne pas coupler le code applicatif à une primitive spécifique : encapsuler le choix dans une couche d’abstraction permet de migrer sans réécriture si une vulnérabilité est découverte.

Quiz

Quiz
  1. 1. Pourquoi l'unicité du nonce est-elle critique, et non sa confidentialité ?

  2. 2. Que peut faire un adversaire qui observe deux messages AES-GCM chiffrés avec le même nonce et la même clé, dans le pire cas ?

  3. 3. Dans un système distribué où deux nœuds utilisent la même clé AES-GCM et chacun maintient un compteur local démarrant à zéro, quel est le problème ?

  4. 4. Pourquoi la comparaison de tags doit-elle s'effectuer en temps constant ?

Ce qu’il faut retenir