AES-GCM, et la seule chose à ne jamais faire avec

AES-GCM est le chiffrement authentifié par défaut du web moderne. Il est rapide, il est partout, et il a un mode de défaillance d’une sévérité inhabituelle.

Ne réemployez jamais un nonce

GCM prend un nonce, un nombre employé une seule fois. Chiffrez deux messages différents avec la même clé et le même nonce, et un attaquant qui voit les deux peut retrouver le XOR des textes clairs.

Ce serait déjà assez grave. C’est pire : le réemploi de nonce laisse aussi fuir la sous-clé d’authentification. Une fois qu’un attaquant la détient, il peut forger des étiquettes valables pour des messages que vous n’avez jamais envoyés, pour cette clé, à partir de là. La confidentialité est entamée ; l’authenticité est détruite.

Il n’y a pas de rattrapage en changeant le nonce après coup. La clé est finie.

Comment cela arrive en pratique

  • Une remise à zéro de compteur. Un processus redémarre, le compteur repart de zéro, la clé n’a pas changé.
  • La même clé sur deux machines, chacune avec son compteur, toutes deux partant du même point.
  • Une source aléatoire faible. Un nonce aléatoire de 96 bits est sûr ; un nonce tiré de quelque chose de prévisible n’est pas aléatoire du tout.
  • Une sauvegarde restaurée, qui rejoue une plage de nonces déjà employés.

Chacun de ces cas est un accident d’exploitation, pas un accident cryptographique. C’est ce qui les rend probables.

Aléatoire, et rotation

Employez 96 bits d’une source aléatoire cryptographique, et faites tourner la clé bien avant que la borne des anniversaires ne rende une collision plausible. Dans JOSE, c’est traité pour vous : chaque JWE porte une clé de chiffrement de contenu fraîche, donc la même clé n’est jamais employée deux fois, par construction.

C’est une décision de conception qui mérite d’être remarquée. La spécification a retiré le piège en rendant le cas dangereux impossible plutôt qu’en mettant en garde contre lui.

Une note d’histoire

php-aes-gcm implémente GCM en PHP pur. Il a été écrit quand PHP n’avait pas d’AEAD natif, avant qu’openssl_encrypt() n’apprenne à rendre une étiquette. Aujourd’hui l’extension fait le travail, et la bibliothèque reste utile là où cette extension n’est pas disponible, ou comme lecture : une implémentation que vous pouvez suivre ligne à ligne est le plus court chemin pour comprendre pourquoi le nonce compte tant.