XAES-256-GCM : AEAD à nonce étendu
(words.filippo.io)- XAES-256-GCM est une nouvelle spécification AEAD qui utilise une clé de 256 bits et un nonce de 192 bits afin de rendre la gestion des nonces moins risquée dans les API de chiffrement de haut niveau
- Un grand nonce permet de générer automatiquement une nouvelle valeur depuis le CSPRNG du système d’exploitation pour chaque message, avec pour objectif un risque de collision de l’ordre de 2⁻³² sur 2⁸⁰ messages
- En interne, il s’agit d’une construction à nonce étendu qui dérive une clé et un nonce de 96 bits à partir de la clé d’entrée et du grand nonce, puis utilise tel quel le standard AES-256-GCM
- L’implémentation de référence en Go tient en moins de 100 lignes avec seulement
crypto/cipheretcrypto/aes, et une partie des 3 appels AES-256 par message peut être précalculée - En mettant l’accent sur la conformité FIPS 140 et la compatibilité avec les bibliothèques, il peut servir de candidat à une API AEAD sans nonce aux côtés de XChaCha20Poly1305 et AES-GCM-SIV
Une AEAD à grand nonce pour les API de haut niveau
- XAES-256-GCM est un algorithme de chiffrement authentifié avec données authentifiées additionnelles (AEAD) qui utilise une clé de 256 bits et un nonce de 192 bits
- Ses objectifs de conception se résument en trois points
- Prise en charge de grands nonces pouvant être générés aléatoirement en toute sécurité, même pour un nombre de messages pratiquement illimité
- Conformité FIPS 140 complète et directe
- Implémentation facile au-dessus des bibliothèques cryptographiques courantes
- Grâce au grand nonce, il devient possible de créer une API qui lit un nouveau nonce depuis le CSPRNG du système d’exploitation pour chaque message, sans que l’utilisateur ait à calculer lui-même la borne d’anniversaire
- En privilégiant la conformité et la compatibilité, il peut être appliqué là où une AEAD est nécessaire, même dans des environnements où d’autres AEAD à grand nonce sont difficiles à utiliser
Une construction à nonce étendu qui réutilise tel quel AES-256-GCM
- XAES-256-GCM est une construction à nonce étendu bâtie au-dessus d’une AEAD existante, comme XChaCha20Poly1305
- À partir de la clé d’entrée et du nonce de 192 bits, elle calcule une clé dérivée et un nonce dérivé pour l’AES-256-GCM interne
- La clé d’entrée et le nonce sont respectivement
KetN - La clé et le nonce AES-256-GCM dérivés sont
KₓetNₓ
- La clé d’entrée et le nonce sont respectivement
Kₓest construit à partir d’appels àAES-256ₖet de la partie initiale du nonce, tandis que les 96 derniers bits du nonce d’entrée sont utilisés commeNₓ- Trois appels à
AES-256ₖsont nécessaires par message- L’un d’eux peut être précalculé pour une clé donnée
- Les deux autres peuvent réutiliser le même key schedule
Une implémentation courte, exprimable avec des composants standards
- L’implémentation de référence en Go compte moins de 100 lignes, optimisation par précalcul et majeure partie du code boilerplate comprises
- L’implémentation Go n’utilise que
crypto/cipheretcrypto/aesde la bibliothèque standard - XAES-256-GCM peut aussi être décrit avec la KDF standard NIST SP 800-108r1 et l’AEAD standard NIST AES-256-GCM
- La KDF est une KDF à compteur
- La PRF est CMAC-AES256
- La clé d’entrée est
Kin - Le label est le caractère ASCII
X, soit0x58 - Le contexte correspond aux 96 premiers bits du nonce d’entrée
- La taille du compteur est de 16 bits
- Le champ optionnel
Lest omis - La sortie est une clé dérivée de 256 bits
- La clé dérivée et les 96 derniers bits du nonce d’entrée sont passés à AES-256-GCM
- Grâce au choix des paramètres, si l’on retire les abstractions KDF et CMAC, l’ensemble n’est qu’un peu plus lent et complexe qu’une simple série d’appels à AES-256 sur un compteur
- Les mêmes paramètres sont pris en charge dans l’API OpenSSL de haut niveau
Implémentations tierces et vecteurs de test
- À la date de l’édition du 29/06/2024, des implémentations tierces ont été ajoutées
- L’implémentation Web Cryptography API utilise une
CryptoKeyAES-CBC de 256 bits - La spécification contient des vecteurs de test pour les deux principaux chemins de code
MSB₁(L) = 0MSB₁(L) = 1
- Des vecteurs de test cumulés, condensant 10 000 ou 1 000 000 d’itérations aléatoires, sont également fournis
Abandon de /11 et alternatives
- Une version précédente envisageait le nom
XAES-256-GCM/11, mais la spécification finale a abandonné/11 /11était une optimisation de performance ; comme l’une des raisons d’utiliser AES-GCM est la conformité FIPS 140, modifier le nombre de tours ferait disparaître cette conformité- Si la conformité FIPS 140 n’est pas un objectif, plusieurs alternatives existent
- AES-GCM-SIV
- Des constructions AEAD modernes fondées sur le cœur AES
- La section Alternatives de la spécification compare chaque option à XAES-256-GCM
Place dans Go et dans une API AEAD sans nonce
- XAES-256-GCM vise à être une AEAD sûre, ennuyeuse, conforme et interopérable
- Son principal cas d’usage est le type d’API de haut niveau que l’on souhaiterait ajouter à Go
- XAES-256-GCM complète XChaCha20Poly1305 et AES-GCM-SIV, et a été conçu comme candidat pour une éventuelle implémentation d’API AEAD sans nonce
- Comme l’ajout d’une construction spécifique à Go dans la bibliothèque standard Go n’est pas privilégié, l’avis des mainteneurs d’autres bibliothèques cryptographiques est nécessaire
1 commentaires
Avis sur Hacker News
La conception est très ingénieuse : comme elle est basée sur CMAC, on peut dériver une clé avec AES-CBC même sans primitives de bas niveau
Du point de vue d’AES-CBC, on peut voir cela comme commençant par
L = AES-CBC-256ₖ(iv = 0¹²⁸, plaintext = 0¹²⁸)[:16]pour créerK1, puis chiffrerM1etM2afin d’obtenirKₓ, avant d’utiliserNₓ = N[12:]On peut considérer qu’AES-CBC-256 ne renvoie que le premier bloc de 128 bits du texte chiffré et jette le bloc de bourrage ; même s’il est impossible de désactiver le bourrage, ce n’est pas si grave, car cela ne coûte que 3 appels AES de plus avec la même clé qu’une implémentation de plus bas niveau
Une implémentation JS fondée sur la WebCrypto API qui exploite cette propriété se trouve sur https://github.com/dchest/xaes ; elle prend directement un
CryptoKeypour AES-CBC et prend aussi en charge les caractéristiques deCryptoKey, comme le stockage dans IndexedDB avecextractable=falseDans ce pseudocode, la moitié des nombres semblent compter des octets, et l’autre moitié des bits ; si l’on ne connaît pas déjà l’algorithme, il est presque impossible de savoir lequel est lequel
Par exemple,
N[:12]a l’air de signifier 12 octets, mais0¹²⁸vaut 16 octets, etXest le caractère réel'X', c’est-à-dire la suite de bits01011000, alors queLest une variable, pas la suite de bits01001100Il semble évident que les mathématiciens n’aiment pas autant que les informaticiens les notations non ambiguës
0¹²⁰10000111sont des suites de bits représentant les coefficients du premier polynôme, dans l’ordre lexicographique, parmi les polynômes irréductibles de degrébayant le nombre minimal de termes non nuls, oùbest la taille de bloc du chiffrement par blocs sous-jacent utilisé par CMACIl n’y a pas d’intention cachée
Ce travail permet d’éviter facilement ce problème en changeant non seulement le nonce, mais aussi la clé à chaque appel AES-GCM
En outre, il n’utilise que de l’AES « ordinaire », généralement disponible quand AES-GCM l’est, et évite de nouvelles constructions complexes qui pourraient encore avoir des faiblesses
Le surcoût par message est d’environ deux petits tampons à chiffrer/déchiffrer avec de l’AES « ordinaire » et un nonce plus long de 192 bits
[1]: https://frereit.de/aes_gcm/
Cela semble éliminer le piège de l’AES-GCM pur, où il faut changer de clé tous les environ 2^32 messages lorsqu’on utilise des nonces aléatoires
Dans AES-GCM, une collision de nonce est catastrophique et permet au moins à un attaquant de signer des messages arbitraires
Il n’est pas indispensable d’utiliser des nonces aléatoires, mais c’est généralement recommandé, et le fait de rendre cela conforme FIPS avec deux briques de base — une fonction de dérivation de clé fondée sur un compteur et GCM pur — est assez malin
Dans AES-GCM standard, 96 bits ne suffisent pas pour éviter les collisions aléatoires, il faut donc utiliser une génération déterministe de nonces
De plus, quelle que soit la façon dont le nonce a été généré, le compteur finit par reboucler et le bloc suivant utilise le même nonce+compteur que le premier bloc ; après 2^32 blocs, il faut donc changer le nonce ou la clé
Vraiment excellent. J’aurais aimé avoir ça il y a quelques années, la dernière fois que j’ai construit un système de fichiers chiffré
Dans les déploiements de systèmes de fichiers à grande échelle, les collisions de nonce sont une grosse source d’inquiétude
2^32 paraît grand, mais sur une baie à l’échelle du pétaoctet, avec des écritures à 100k IOPS par seconde et en comptant sur l’aléa d’un générateur pseudo-aléatoire, la probabilité de collision est pratiquement garantie
[1] https://en.m.wikipedia.org/wiki/CAESAR_Competition
Cela signifie seulement que deux blocs partagent la même clé de chiffrement, non ?
Si l’on ne connaît le texte en clair d’aucun des blocs, je ne vois pas en quoi cela affaiblit la sécurité du système
J’aimerais que cela soit utilisé dans une variante de age conforme FIPS pour le chiffrement de fichiers d’archivage
Lors d’un audit bancaire, age a été rejeté pour cet usage parce qu’il utilise ChaCha, tandis que la partie clé publique X25519 d’age a été jugée acceptable. Je pensais que X25519 avait été approuvé relativement récemment par le NIST
Je n’ai pas d’expérience en Go, mais à lire la spécification de age, cela semble pouvoir s’y intégrer directement, et je pourrais tenter le coup si j’ai le temps
On pourrait l’appeler « cage », pour « compliant actually good encryption »
1: https://github.com/FiloSottile/age
En tant que non-cryptographe, je me demande pourquoi utiliser un nonce de 192 bits et pas 256 bits
Dans les applications pratiques, ces bits supplémentaires ne me semblent pas représenter un coût
On pourrait allonger l’entrée de CMAC, mais il faudrait alors exécuter davantage de fois la fonction de bloc AES-256, et on se heurterait aussi à des problèmes pénibles de contrôle de clé dans la fonction de dérivation de clé CMAC
C’est similaire à la raison pour laquelle XChaCha20Poly1305 utilise un nonce de 192 bits, et c’est aussi un léger avantage que ce soit cohérent avec les autres grands AEAD à nonce étendu
Il est dit « risque de collision de 2⁻³² avec 2⁸⁰ messages » ; le fait que la taille de bloc AES ne soit que de 128 bits ne pose-t-il pas problème avant cela ?
XAES dérive une grande clé par message et obtient donc ce qu’on appelle souvent une garantie meilleure que la borne d’anniversaire
Sans davantage de contexte sur la raison pour laquelle vous pensez que cela poserait problème, il est difficile de répondre plus en détail
« Sûr, ennuyeux, compatible avec les exigences de conformité, interopérable »
C’est mon genre de technologie préféré
Bien. C’est vraiment agréable d’avoir une construction fondée sur le NIST
Cela dit, c’est dommage de renoncer à plusieurs fonctionnalités utiles des fonctions de dérivation de clé du NIST, comme les étiquettes et le contexte
Je comprends que ce soit sacrifié pour minimiser le nombre d’appels AES, mais, surtout pour les messages de plus de quelques centaines d’octets, j’aurais plutôt privilégié une séparation cryptographique forte plutôt que d’économiser quelques appels AES
Enfin, les nonces GCM aléatoires de plus de 96 bits sont clairement très mal compris, et offrent de meilleures garanties que les nonces de 96 bits[1]
Bien sûr, si l’on peut dériver une nouvelle clé par message, c’est nettement préférable
[1] https://neilmadden.blog/2024/05/23/galois-counter-mode-and-r...