ByteSub est une application avec les propriétés suivantes :
Dans notre cas, les ensembles E et F sont les mêmes. il s'agit de GF(28).
La bijectivité permet de s'assurer que lors du chiffrement tout les éléments aient une image différente.
Ainsi lors du déchiffrement, il n'y aura pas d'incohérence, une fonction bijective étant inversible, tel que son inverse est aussi une fonction bijective.
La non linéarité permet de se protéger de certaines attaques (voir sources).
Le but de ByteSub est d'effectuer une substitution octet (byte) par octet. Cela s'effectue en deux étapes distinctes.
Dans cette partie, on va reprendre A =
, dans le but de créer un exemple.
Tout d'abord on remplace la valeur
(un mot du bloc de donnée) par son inverse dans GF(28).
Étant donné que nous sommes dans un corps, il faut préciser quelle opération nous utilisons.
Dans ce cas, il s'agit de l'inverse dans le groupe multiplicatif, d'élément neutre 0x01.
Dans ce groupe, 0x00 n'ayant pas d'inverse, il est son propre inverse par convention.
Cela peut se faire via une table :
(Pour passer du binaire a l'héxadécimal, voir l'onglet sur l'algorithme AES).
Celle-ci peut directement être codée "en dur" dans un programme, elle ne varie jamais.
On a donc :
Exemple :
Si l'on reprend l'inverse de A, on a donc :
A-1 =
Dans cette seconde étape, on modifie la valeur en la multipiant par un vecteur puis en sommant un terme constant, le tout modulo 2.
Le fait que cette fonction soit bijective permettra plus tard le déchiffrement de cette étape.
Ainsi :
Avec la fonction f() correspondant à :
Exemple :
On reprend
Après calcul, on va trouver
Il est possible de simplifier cette étape. En effet, cette transformation f() est une bijection.
Chaque élément de GF(28) possède une image unique et un antécédent unique.
De plus, l'inverse d'un élément est unique.
En effet :
L'inverse est donc unique pour chaque élément, pour l'opération *.
Chaque élément de GF(28) a donc un inverse unique et une image unique par f().
L'ensemble GF est finis, il est donc possible de calculer ByteSub pour chacun de ses éléments.
Cela donne la table suivante (ici en notation hexadécimale) :
On peut voir qu'il n'y a aucune symétrie ou de point spécifique.
Exemple :
SI l'on reprend A =
On peut directement faire la correspondance (inverse et passage par f()).
Cela donne bien
ByteSub étant bijective, il est possible de construire sa fonction inverse.
pour la fonction f(), elle représente un système de 8 inconnues à 8 équations, il est donc possible de le résoudre.
Cela permet d'obtenir la fonction suivante :
De plus, comme on peut le voir dans la table des inverses, si a inverse de b alors b inverse de a.
On peut donc réutiliser cette table:
Ainsi, il est possible de remonter ByteSub. Tout d'abord en trouvant la fonction inverse f-1().
Ensuite, de reprendre l'inverse du résultat, pour retomber sur l'élement initial.
De même que pour ByteSub, il est possible de précalculer le résultat pour chaque élément :
Si vous voulez, vous pouvez vérifier :