Recherche de collisions sur une version simplifiée de MD5 1

Transcription

Recherche de collisions sur une version simplifiée de MD5 1
Recherche de collisions sur une version simplifiée de MD5
Le but de cet exercice est de programmer une version simplifiée de la fonction de hachage
MD5, qui produira des hachés de 40 bits, et de trouver des collisions sur cette fonction à l’aide
du paradoxe des anniversaires.
1
Fonction de hachage
La totalité du code concernant l’implémentation de la fonction de hachage est à écrire
dans un fichier hachage.c. Cette partie sera utilisée par la suite dans une fonction principale
située dans un autre fichier.
La fonction de hachage à programmer prend en entrée, comme MD5, un message de
512 bits (représenté par 16 mots de 32 bits) et produit un haché de 40 bits stockés sur 2 mots
de 32 bits. Ces 40 bits sont en fait les 40 premiers bits de la sortie de MD5 après seulement
16 tours (sans l’ajout des constantes additives).
1.1
Fonctions intermédiaires
Programmez les deux fonctions (ou macros) intermédiaires suivantes qui seront utilisées
à chaque itération de la fonction de hachage.
– selection: cette fonction prend en argument 3 mots de 32 bits, u, v et w. Elle retourne
un mot de 32 bits dont le i-ème bit correspond au i-ème bit de v si le i-ème bit de u
vaut 1, et au i-ème bit de w sinon.
– rotation: cette fonction prend comme premier argument un mot de 32 bits x et, comme
deuxième argument, un entier non signé n. Elle retourne un mot de 32 bits qui correspond au décalé circulaire de x de n positions vers la gauche.
1.2
Fonction de hachage
La fonction de hachage prend en entrée un message de 16 mots de 32 bits, noté message[i]
pour i variant de 0 à 15. Elle utilise 4 variables intermédiaires, notées a, b, c, d, qui sont
initialisées par les valeurs hexadécimales suivantes :
a = 0x67452301;
b = 0xefcdab89;
c = 0x98badcfe;
d = 0x10325476;
La fonction effectue alors 16 itérations. L’itération numéro i se déroule de la manière suivante :
– Calculer une valeur intermédiaire
t = a + selection(b,c,d) + message[i]
– Remplacer le quadruplet (a, b, c, d) par le quadruplet (d, b + rotation(t, s[i]),
b, c) où le nombre de positions du décalage au tour i, s[i], est défini par
s[i] =


7


 12
si
si
si
si

17



22
1
i ≡ 0 mod 4
i ≡ 1 mod 4
i ≡ 2 mod 4
i ≡ 3 mod 4
Après le 16e tour, le haché est constitué de la valeur de a (32 bits), et des 8 premiers bits de b.
On stockera le haché obtenu dans un tableau de 2 entiers de 32 bits. Par souci de simplicité,
il est conseillé de passer ce tableau en argument de la fonction (l’allocation ayant été faite
avant l’appel à la fonction de hachage).
1.3
Vérification
Vérifiez que votre programme se déroule normalement en écrivant un programme principal
dans un deuxième fichier (par exemple main.c) qui réalise un appel de la fonction de hachage
sur un message aléatoire de 512 bits. Dans toute la suite, un message aléatoire sera constitué
de 16 mots générés par 16 appels consécutifs à la fonction random.
La compilation des deux fichiers sera faite de préférence à l’aide d’un fichier Makefile.
2
Recherche de collisions
Le code de cette partie sera situé dans le même fichier source que la vérification mentionnée
ci-dessus.
Le but de cette partie est de générer des messages de 512 bits aléatoires jusqu’à en trouver
deux qui aient le même haché (un tel couple est appelé collision). On rappelle que, d’après le
paradoxe des anniversaires, il faut de l’ordre de 2m/2 messages en moyenne pour trouver une
collision pour des hachés de m bits.
Les couples (message, haché) seront stockés sous forme d’une table de hachage (un tableau
de listes) indexée par les 20 premiers bits du haché. Autrement dit, ce tableau de 220 listes
sera tel que la ligne tab[i] correspondra aux messages dont les 20 premiers bits du haché
prennent la valeur i. Chaque élément de la liste tab[i] sera constitué du message et des 20
derniers bits du haché correspondant.
En utilisant cette technique, programmez l’algorithme de recherche de collisions suivant :
Jusqu’à ce qu’on trouve une collision, itérer :
– tirer un message aléatoire de 512 bits
– calculer son haché
– vérifier si ce haché a déjà été trouvé
– si oui, afficher les 2 messages et leurs hachés
– sinon, insérer le message dans la table de hachage.
2