La S-box de Rijndael est une opération fréquemment utilisée dans le chiffrement et le déchiffrement AES . Il est généralement implémenté comme une table de recherche de 256 octets. C'est rapide, mais cela signifie que vous devez énumérer une table de recherche de 256 octets dans votre code. Je parie que quelqu'un dans cette foule pourrait le faire avec moins de code, étant donné la structure mathématique sous-jacente.
Écrivez une fonction dans votre langue préférée qui implémente la S-box de Rijndael. Le code le plus court gagne.
code-golf
math
cryptography
Keith Randall
la source
la source
Réponses:
Ruby, 161 caractères
Afin de vérifier la sortie, vous pouvez utiliser le code suivant pour l'imprimer sous forme de tableau:
la source
GolfScript, 60 caractères
Ce code définit une fonction nommée
S
qui prend un octet et lui applique la S-box Rijndael. (Il utilise également une fonction d'assistance interne nomméer
pour enregistrer quelques caractères.)Cette implémentation utilise une table de logarithmes pour calculer les inverses GF (2 8 ), comme suggéré par Thomas Pornin . Pour enregistrer quelques caractères, la table de logarithme entière est recalculée pour chaque octet d'entrée; malgré cela, et bien que GolfScript soit un langage très lent en général, ce code ne prend que 10 ms environ pour traiter un octet sur mon ancien ordinateur portable. Le précalcul de la table de logarithme (as
L
) l'accélère jusqu'à environ 0,5 ms par octet, au coût modeste de trois caractères supplémentaires:Pour plus de commodité, voici un harnais de test simple qui appelle la fonction
S
, telle que définie ci-dessus, pour calculer et imprimer l'ensemble de la S-box en hexadécimal comme sur Wikipedia :Essayez ce code en ligne.
(La démo en ligne précalcule la table de logarithme pour éviter de prendre trop de temps. Même ainsi, le site GolfScript en ligne peut parfois expirer de manière aléatoire; il s'agit d'un problème connu avec le site, et un rechargement le corrige généralement.)
Explication:
Commençons par le calcul de la table de logarithme, et plus précisément avec la fonction d'assistance
r
:Cette fonction prend deux entrées sur la pile: un octet et un masque de bits de réduction (une constante entre 256 et 511). Il duplique l'octet d'entrée, multiplie la copie par 2 et, si le résultat dépasse 255, le XOR avec le masque de bits pour le ramener sous 256.
Dans le code de génération de la table de journal, la fonction
r
est appelée avec le masque de réduction 283 = 0x11b (qui correspond au polynôme de réduction Rijndael GF (2 8 ) x 8 + x 4 + x 3 + x + 1), et le résultat est XORed avec l'octet d'origine, en le multipliant effectivement par 3 (= x + 1, comme un polynôme) dans le champ fini de Rijndael. Cette multiplication est répétée 255 fois, à partir de l'octet 1, et les résultats (plus un zéro octet initial) sont collectés dans un tableau de 257 élémentsL
qui ressemble à ceci (partie centrale omise):La raison pour laquelle il y a 257 éléments est que, avec le 0 précédant et 1 se produisant deux fois, nous pouvons trouver l'inverse modulaire de tout octet donné simplement en recherchant son index (de base zéro) dans ce tableau, en le niant et en regardant jusqu'à l'octet à l'index négatif dans le même tableau. (Dans GolfScript, comme dans de nombreux autres langages de programmation, les index de tableau négatifs comptent à rebours à partir de la fin du tableau.) En effet, c'est exactement ce que fait le code
L?~)L=
au début de la fonctionS
.Le reste du code appelle la fonction d'assistance
r
quatre fois avec le masque binaire de réduction 257 = 2 8 + 1 pour créer quatre copies à rotation binaire de l'octet d'entrée inversé. Ceux-ci sont tous collectés dans un tableau, avec la constante 99 = 0x63, et XOR ensemble pour produire la sortie finale.la source
x86-64 Code machine -
23 22 2019 octetsUtilise le jeu d'instructions AES-NI
En utilisant les conventions d'appel Windows, prend un octet et sort un octet. Il n'est pas nécessaire d'inverser le
ShiftRows
car cela n'affecte pas le premier octet.la source
La table peut être générée sans calculer les inverses dans le champ fini GF (256), en utilisant des logarithmes. Il ressemblerait à ceci (code Java,
int
pour éviter les problèmes avec lebyte
type signé ):L'idée est que 3 est un générateur multiplicatif de GF (256) *. Le tableau
t[]
est tel qu'ilt[x]
est égal à 3 x ; puisque 3 255 = 1, nous obtenons que 1 / (3 x ) = 3 255-x .la source
0x1B
(un 1 dans le littéral hexadécimal) au lieu de0x11B
int
type est 32 bits en Java; Je dois annuler le bit supérieur.GolfScript (82 caractères)
Utilise les variables globales
A
etB
, et crée la fonction comme variable globaleS
.L'inversion de Galois est une force brute; J'ai expérimenté avec une
mul
fonction séparée qui pourrait être réutilisée pour la transformation affine post-inversion, mais elle s'est avérée plus coûteuse en raison du comportement de débordement différent.C'est trop lent pour une démonstration en ligne - cela expirerait même sur les deux premières lignes du tableau.
la source
Python, 176 caractères
Cette réponse est pour le commentaire-question de Paŭlo Ebermann sur la façon de rendre la fonction à temps constant. Ce code correspond à la facture.
la source
ré
cela peut générer la table de recherche au moment de la compilation, je pourrais en économiser en faisant ubyte un paramètre générique
éditez directement
ubyte
àubyte
sans recherches de tableau, sans branchement et boucles entièrement déroulablesedit2 a utilisé l'algo de @Thomas pour créer la table de recherche
la source
Stax , 53 octets
Exécuter et déboguer
Je n'ai aucune compréhension particulière des S-box. Il s'agit d'une conversion de la solution de Thomas Pornin (8 ans!) .
la source