L'AES (Advanced Encryption Standart) est entièrement défini par la publication "FIPS PUB NIST 197"
On trouvera ici une étude très détaillée sur son implémentation en version 256 bits pour la clef
d'encryptage en langage C.
Les principaux tests de validation fournis par la FIPS sont implémentés.
Les fichiers sources de l'ensemble des logiciels : encryptage, decryptage, tests
sont disponibles dans le fichier compressé sources.tar.gz à l'url : Les sources
L'AES effectue ses opérations sur des bytes ( 8 bits non signés) qui sont vus
comme codant les éléments du corps de Galois GF(`2^8`).
On effectue un bref rappel sur GF(`2^8`) et son arithmétique.
L'implémentation qui est faite de cette dernière est basée sur les logarithmes discrets .
L'AES découpe les données en groupes de 16 bytes .
Chaque groupe fait l'objet d'un traitement en soi mais identique pour tous.
Trois sortes de clefs d'encryptage sont proposées : 128, 192 , 256 bits.
Les fonctions mises en oeuvre tant au cryptage qu'au décryptage sont les mêmes
pour ces trois sortes de clefs mais des différences assez importantes apparaissent
dans leur exploitation par l'algorithme de chiffrement (resp déchiffrement) .
Dans tout ce qui suit la clef d'encryptage est de 256 bits.
Initialisations générales .
Elles précèdent le traitement proprement dit des données .
Sont concernées :
L'initialisation des tableaux relatifs aux logarithmes discrets.
La génération des clefs ( 15 en tout) toutes de 128 bits définies à partir de la clef d'encryptage.
Nota: La clef d'encryptage de 256 bits définit les valeurs des 2 premières clefs.
La S-Box ,un tableau de 16x16 bytes dont le rôle est très important.
// Initialisations des tableaux utilisés en arithmétique ( Log discrets)
InitLog() ;
// Initialisationj de la S-Box
InitSBox() ;
// Initialisation du tableau des 15 clefs
InitKey(CryptKey) ;
L'encryptage .
Comme on l'a vu les données sont constituées en groupes de 16 bytes.
Les fonctions qui interviennent dans l'algorithme de cryptage portent toutes sur le tableau State[4][4]
de type byte dont l'état varie au cours du traitement.
Ce tableau est initialisé pour un groupe donné par la fonction InitState().
Le traitement d'un groupe se fait en 15 rounds :
A chacun de ces rounds est associé une clef différente (cf AddRoundKey()).
Le premier round (round 0) est un round d'initialisation .
Suivent 13 rounds de structure identique.
Un round final (round 14) distinct des précédents termine l'encryptage du groupe.
#define byte unsigned char
byte State[4][4] ; // tableau global associé à l'encryptage d'un groupe
void EnCrypt(byte *grp){ ; // encrypte un groupe de 16 bytes
unsigned rnd ;
InitState(grp) ; // State <-- groupe
// Encryptage du groupe
AddRoundKey(0) ; // round 0
for(rnd=1; rnd < 14; rnd++){ // rounds 1 à 13
SubByte() ;
ShiftRows() ;
MixColumns() ;
AddRoundKey(rnd) ;
}
SubByte() ; // round 14
ShiftRows() ;
AddRoundKey(14) ;
}
Le décryptage.
La structure du décryptage diffère légèrement de celle de l'encryptage.
Les fonctions ShiftRows(), SubBytes(), MixColumns() étant remplaçées par leurs inverses.
void DeCrypt(byte *grp){ // décrypte un groupe de 16 bytes
unsigned rnd ;
InitState(grp) ;
// Décryptage du groupe
AddRoundKey(14) ;
for(rnd = 13; rnd > 0 ; rnd--){
InvShiftRows() ;
InvSubBytes() ;
AddRoundKey(rnd) ;
InvMixColumns() ;
}
InvShiftRows() ;
InvSubBytes() ;
AddRoundKey(0) ;
}