Pour commencer, téléchargez l'archive suivante:
Vous aurez besoin de la librairie tqdm pour afficher la progression de vos calculs:
pip install tqdm
Dans ce TD, nous allons implémenter des tables arc-en-ciel (pédagogiques). Nous nous intéresserons à la fonction
de hachage MD5. Pour simplifier, nous ne considérerons que des mots de passe de taille 5, avec le jeu de
32 caractères suivant: abcdefghijklmnopqrstuvwxyz123456.
Dans tools.py, vous trouverez les fonctions suivantes:
generate_password: génère un mot de passe aléatoire,md5_hash(password): calcule l'empreinte MD5 d'une chaîne,reduce(hash, level): applique une fonction de réduction à une empreinte,all_passwords(): retourne un itérateur sur tous les mots de passe possibles.Lisez et testez le code de bruteforce.py. Il s'agit d'une solution naïve pour retrouver un mot de passe
à partir de son empreinte MD5.
Le code ne s'arrêtant pas lorsque le mot de passe a été trouvé, constatez le temps d'exécution pour trouver un mot de passe.
Lisez le code de store_all.py. Il s'agit d'une solution naïve pour pré-calculer toutes les empreintes
possibles.
Si vous avez de l'espace disque, vous pouvez tester et constater la taille du fichier all_passwords.pkl
ainsi généré: 1.4 Go!
Le fichier all_passwords.pkl n'est absolument pas optimisé en terme de stockage. Pensez à supprimer
ce fichier après cette partie, il n'est pas nécessaire pour la suite.
Créez maintenant un fichier rainbow.py, c'est dans ce fichier que vous implémenterez les tables arc-en-ciel.
Nous utiliserons les paramètres suivants:
# Taille des chaînes arc-en-ciel
chains_length = 256
# Taille de la table arc-en-ciel
rainbow_table_size = 200_000
Écrivez le code de la fonction compute_chain(), qui calcule une chaîne arc-en-ciel, en partant d'un mot de passe aléatoire.
def compute_chain() -> tuple:
"""
Calcule une chaîne arc-en-ciel
Retourne un tuple (password, hash), où:
- password est le premier mot de passe de la chaîne,
- hash est le dernier hash
"""
Écrivez le code de la fonction compute_rainbow_table(), qui calcule une table arc-en-ciel:
def compute_rainbow_table():
"""
Calcule une table arc-en-ciel, et la stocke dans un
fichier rainbow_table.pkl
"""
Vous stockerez les chaînes arc-en-ciel dans un dictionnaire, où chaque clé est le hash du dernier mot de passe, et chaque valeur est une liste de mots de passe initiaux possibles.
Écrivez à présent le code de la fonction load_rainbow_table(), qui charge une table arc-en-ciel depuis un
fichier:
def load_rainbow_table() -> dict:
"""
Charge une table arc-en-ciel depuis un fichier
"""
Constatez la taille du fichier rainbow_table.pkl ainsi généré.
Enfin, écrivez le code de la fonction crack_password(), qui retrouve un mot de passe à partir de son empreinte,
et de la table arc-en-ciel:
def crack_password(target_hash: str, rainbow_table: dict) -> None:
"""
Retrouve un mot de passe à partir de son empreinte
"""
Quel est le temps d'exécution pour retrouver un mot de passe à partir de son empreinte, avec la table arc-en-ciel ?