From 80c1f1b10606b12f0b9376c044a63c425c881a0a Mon Sep 17 00:00:00 2001 From: Eunock-web Date: Sat, 2 Aug 2025 06:20:34 +0200 Subject: [PATCH 01/16] =?UTF-8?q?Int=C3=A9gration=20de=20AesCbcAnalyzer=20?= =?UTF-8?q?dans=20DetecteurCryptoOrchestrateur.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/detecteur_crypto.py | 104 +++++++++++++++++++++++++++++++++++----- 1 file changed, 93 insertions(+), 11 deletions(-) diff --git a/src/detecteur_crypto.py b/src/detecteur_crypto.py index 45c6775..ef27e8f 100644 --- a/src/detecteur_crypto.py +++ b/src/detecteur_crypto.py @@ -1,17 +1,99 @@ -import AesCbcAnalyzer -from crypto_analyzer import identifier_algo +# Import des modules +import os + +# Import des modules d'analyse +from .analyzers.aes_cbc_analyzer import Aes_Cbc_Analyzer + +class ResultatAnalyse: + """ + Classe représentant un résultat d'analyse. + """ + def __init__(self, algo: str, cle: bytes, texte_dechiffre: bytes): + self.algo = algo + self.cle = cle + self.texte_dechiffre = texte_dechiffre -""" - Classe principale qui centralise tout: - -Lance l’analyse des fichiers et identifie l'algorithme probable, - -Lance les attaquespar dictionnaire, - -Lance et coordonnes le processus de dechiffrement -""" class DetecteurCryptoOrchestrateur: """ - Initialisation de l'analyseur AES-CBC + Classe principale qui centralise tout: + -Lance l'analyse des fichiers et identifie l'algorithme probable, + -Lance les attaques par dictionnaire, + -Lance et coordonnes le processus de dechiffrement """ + def __init__(self): - self.aes_cbc_analyzer = AesCbcAnalyzer() - + """ + Initialisation de tous les modules d'analyse disponibles (AES-CBC) pour le moment + """ + self.analyzers = { + "AES-CBC": Aes_Cbc_Analyzer(), + } + def Analyser_fichier_uniquement(self, chemin_fichier_chiffre: str) -> ResultatAnalyse: + """ + Analyse un seul fichier chiffré et retourne le résultat de l'analyse. + + Args: + chemin_fichier_chiffre(str): chemin du fichier chiffré à analyser + + Returns: + ResultatAnalyse: résultat de l'analyse + """ + try: + #Initialisation des variables + algorithme_detecte = "" + cle = b"" + texte_dechiffre = b"" + + #Parcours des algorithmes disponibles + for nom_algo, analyzer in self.analyzers.items(): + score_probabilite = analyzer.identifier_algo(chemin_fichier_chiffre) # ← Retourne un float + print(f"{nom_algo}: score {score_probabilite:.2f}") + + if score_probabilite > 0.5: # ← Comparaison correcte avec le seuil + algorithme_detecte = nom_algo # ← Stockage du nom de l'algorithme + print(f"Algorithme détecté: {algorithme_detecte} (score: {score_probabilite:.2f})") + + # Génération des clés candidates + cles_candidates = analyzer.generer_cles_candidates("dicoEn") + print(f"{len(cles_candidates)} clés candidates générées") + + # Test de déchiffrement avec la première clé (pour l'exemple) + if cles_candidates: + texte_dechiffre = analyzer.dechiffrer(chemin_fichier_chiffre, cles_candidates[0]) + if texte_dechiffre: + cle = cles_candidates[0] + print("Déchiffrement réussi avec la première clé!") + else: + print("Déchiffrement échoué avec la première clé") + break + + if not algorithme_detecte: + print("Aucun algorithme détecté avec confiance suffisante") + + return ResultatAnalyse(algorithme_detecte, cle, texte_dechiffre) + except Exception as e: + print(f"Erreur lors de l'analyse du fichier {chemin_fichier_chiffre}: {str(e)}") + return ResultatAnalyse("", b"", b"") + + + def Analyser_fichiers_sequentiels(self, dossier_chiffres: str) -> list[ResultatAnalyse]: + """ + Analyse plusieurs fichiers chiffrés dans un dossier et retourne les résultats de l'analyse. + + Args: + dossier_chiffres(str): dossier contenant les fichiers chiffrés à analyser + + Returns: + list[ResultatAnalyse]: liste des résultats d'analyse pour chaque fichier + """ + try: + resultats = [] + for fichier_chiffre in os.listdir(dossier_chiffres): + chemin_fichier_chiffre = os.path.join(dossier_chiffres, fichier_chiffre) + resultat = self.Analyser_fichier_uniquement(chemin_fichier_chiffre) + resultats.append(resultat) + return resultats + except Exception as e: + print(f"Erreur lors de l'analyse des fichiers: {str(e)}") + return [] \ No newline at end of file From a41256c29fe1093e8f9e67072cffdf19d0ef6683 Mon Sep 17 00:00:00 2001 From: Eunock-web Date: Sat, 2 Aug 2025 16:38:41 +0200 Subject: [PATCH 02/16] Debut de l'implementation du code dans la classe principale avec le menu --- src/detecteur_crypto.py | 6 +-- src/interface_console.py | 80 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 5 deletions(-) diff --git a/src/detecteur_crypto.py b/src/detecteur_crypto.py index ef27e8f..8e25c99 100644 --- a/src/detecteur_crypto.py +++ b/src/detecteur_crypto.py @@ -47,11 +47,11 @@ def Analyser_fichier_uniquement(self, chemin_fichier_chiffre: str) -> ResultatAn #Parcours des algorithmes disponibles for nom_algo, analyzer in self.analyzers.items(): - score_probabilite = analyzer.identifier_algo(chemin_fichier_chiffre) # ← Retourne un float + score_probabilite = analyzer.identifier_algo(chemin_fichier_chiffre) # Retourne un float print(f"{nom_algo}: score {score_probabilite:.2f}") - if score_probabilite > 0.5: # ← Comparaison correcte avec le seuil - algorithme_detecte = nom_algo # ← Stockage du nom de l'algorithme + if score_probabilite > 0.5: # Comparaison correcte avec le seuil + algorithme_detecte = nom_algo # Stockage du nom de l'algorithme print(f"Algorithme détecté: {algorithme_detecte} (score: {score_probabilite:.2f})") # Génération des clés candidates diff --git a/src/interface_console.py b/src/interface_console.py index 5f8b70b..8e91cfe 100644 --- a/src/interface_console.py +++ b/src/interface_console.py @@ -3,6 +3,8 @@ from rich.markdown import Markdown from rich import print from rich.prompt import Prompt +from detecteur_crypto import Analyser_fichier_uniquement +from detecteur_crypto import Analyser_fichier_sequentiels import time, os install() @@ -50,7 +52,81 @@ def default_menu(self): self.console.print(menuTag,menuOption) time.sleep(0.04) - self.prompt.ask("Veuillez choisir une option ",choices=["1","2","3","4","5","6"]) + choix = self.prompt.ask("Veuillez choisir une option ",choices=["1","2","3","4","5","6"]) + if choix == "1": + self.menu_1() + elif choix == "2": + self.menu_2() + elif choix == "3": + self.menu_3() + elif choix == "4": + self.menu_4() + elif choix == "5": + self.menu_5() + elif choix == "6": + self.menu_6() -consoleInterface() \ No newline at end of file + def menu_1(self): + self.console.clear() + self.dynamiqueText("Analyse d'un fichier spécifique","green") + self.dynamiqueText("Veuillez entrer le chemin du fichier :","white") + time.sleep(0.04) + chemin_fichier = self.prompt.ask("Veuillez entrer le chemin du fichier : ") + resultat = Analyser_fichier_uniquement(self,chemin_fichier) + self.console.clear() + self.dynamiqueText("Analyse en cours...","green") + time.sleep(0.04) + self.console.clear() + self.dynamiqueText("Analyse terminée","green") + time.sleep(0.04) + self.default_menu() + + def menu_2(self): + self.console.clear() + self.dynamiqueText("Mission complète automatique","green") + self.dynamiqueText("Veuillez entrer le chemin du dossier :","white") + time.sleep(0.04) + chemin_dossier = self.prompt.ask("Veuillez entrer le chemin du dossier : ") + self.console.clear() + self.dynamiqueText("Mission en cours...","green") + time.sleep(0.04) + self.console.clear() + self.dynamiqueText("Mission terminée","green") + time.sleep(0.04) + self.default_menu() + + def menu_3(self): + self.console.clear() + self.dynamiqueText("Attaque par dictionnaire manuelle","green") + self.dynamiqueText("Veuillez entrer le chemin du fichier :","white") + time.sleep(0.04) + chemin_fichier = self.prompt.ask("Veuillez entrer le chemin du fichier : ") + self.console.clear() + self.dynamiqueText("Attaque en cours...","green") + time.sleep(0.04) + self.console.clear() + self.dynamiqueText("Attaque terminée","green") + time.sleep(0.04) + self.default_menu() + + def menu_4(self): + self.console.clear() + self.dynamiqueText("Affichage des rapports","green") + time.sleep(0.04) + self.default_menu() + + def menu_5(self): + self.console.clear() + self.dynamiqueText("Système d'aide intégré","green") + time.sleep(0.04) + self.default_menu() + + def menu_6(self): + self.console.clear() + self.dynamiqueText("Au revoir !","green") + time.sleep(0.04) + self.console.clear() + self.console.exit() + +consoleInterface() From cac3bf59d22738e187a90332460fa2bd42f20187 Mon Sep 17 00:00:00 2001 From: Eunock-web Date: Sat, 2 Aug 2025 16:50:56 +0200 Subject: [PATCH 03/16] Suite de l'implementation du code dans la classe principale avec le menu --- src/interface_console.py | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/interface_console.py b/src/interface_console.py index 8e91cfe..0eb9537 100644 --- a/src/interface_console.py +++ b/src/interface_console.py @@ -53,19 +53,27 @@ def default_menu(self): time.sleep(0.04) choix = self.prompt.ask("Veuillez choisir une option ",choices=["1","2","3","4","5","6"]) - if choix == "1": - self.menu_1() - elif choix == "2": - self.menu_2() - elif choix == "3": - self.menu_3() - elif choix == "4": - self.menu_4() - elif choix == "5": - self.menu_5() - elif choix == "6": - self.menu_6() - + try: + if choix == "1": + self.menu_1() + elif choix == "2": + self.menu_2() + elif choix == "3": + self.menu_3() + elif choix == "4": + self.menu_4() + elif choix == "5": + self.menu_5() + elif choix == "6": + self.menu_6() + + while choix > "6" or choix < "1": + self.console.print("Veuillez entrer un nombre entre 1 et 6") + choix = self.prompt.ask("Veuillez choisir une option ",choices=["1","2","3","4","5","6"]) + except ValueError: + self.console.print("Veuillez entrer un nombre entre 1 et 6") + except Exception as e: + self.console.print(f"Une erreur est survenue : {e}") def menu_1(self): self.console.clear() @@ -73,7 +81,7 @@ def menu_1(self): self.dynamiqueText("Veuillez entrer le chemin du fichier :","white") time.sleep(0.04) chemin_fichier = self.prompt.ask("Veuillez entrer le chemin du fichier : ") - resultat = Analyser_fichier_uniquement(self,chemin_fichier) + resultat = Analyser_fichier_uniquement(chemin_fichier) self.console.clear() self.dynamiqueText("Analyse en cours...","green") time.sleep(0.04) From 93fd27d840c1ee137beea52b504e30781c00f978 Mon Sep 17 00:00:00 2001 From: wesley-kami Date: Mon, 4 Aug 2025 16:55:26 +0100 Subject: [PATCH 04/16] Update de l'option quitter --- src/interface_console.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/interface_console.py b/src/interface_console.py index 0eb9537..fee6eb5 100644 --- a/src/interface_console.py +++ b/src/interface_console.py @@ -3,8 +3,8 @@ from rich.markdown import Markdown from rich import print from rich.prompt import Prompt -from detecteur_crypto import Analyser_fichier_uniquement -from detecteur_crypto import Analyser_fichier_sequentiels +# from detecteur_crypto import Analyser_fichier_uniquement +# from detecteur_crypto import Analyser_fichier_sequentiels import time, os install() @@ -39,7 +39,7 @@ def dynamiqueText(self,text,color): def default_menu(self): self.console.clear() - self.dynamiqueText("😈​ Bienvenue sur Forensic je suis Crypto votre assitant IA minimaliste🤖​ ","green") + self.dynamiqueText("😈​ Bienvenue sur Forensic je suis Crypto votre assitant IA minimaliste 🤖​ ","green") self.dynamiqueText("En quoi puis-je vous aider ? :","white") time.sleep(0.04) menuTag = Markdown("# Menu",style="blue") @@ -80,22 +80,22 @@ def menu_1(self): self.dynamiqueText("Analyse d'un fichier spécifique","green") self.dynamiqueText("Veuillez entrer le chemin du fichier :","white") time.sleep(0.04) - chemin_fichier = self.prompt.ask("Veuillez entrer le chemin du fichier : ") - resultat = Analyser_fichier_uniquement(chemin_fichier) + # chemin_fichier = self.prompt.ask("Veuillez entrer le chemin du fichier : ") + # resultat = Analyser_fichier_uniquement(chemin_fichier) self.console.clear() self.dynamiqueText("Analyse en cours...","green") time.sleep(0.04) self.console.clear() self.dynamiqueText("Analyse terminée","green") time.sleep(0.04) - self.default_menu() + # def menu_2(self): self.console.clear() self.dynamiqueText("Mission complète automatique","green") self.dynamiqueText("Veuillez entrer le chemin du dossier :","white") time.sleep(0.04) - chemin_dossier = self.prompt.ask("Veuillez entrer le chemin du dossier : ") + # chemin_dossier = self.prompt.ask("Veuillez entrer le chemin du dossier : ") self.console.clear() self.dynamiqueText("Mission en cours...","green") time.sleep(0.04) @@ -109,7 +109,7 @@ def menu_3(self): self.dynamiqueText("Attaque par dictionnaire manuelle","green") self.dynamiqueText("Veuillez entrer le chemin du fichier :","white") time.sleep(0.04) - chemin_fichier = self.prompt.ask("Veuillez entrer le chemin du fichier : ") + # chemin_fichier = self.prompt.ask("Veuillez entrer le chemin du fichier : ") self.console.clear() self.dynamiqueText("Attaque en cours...","green") time.sleep(0.04) @@ -132,9 +132,8 @@ def menu_5(self): def menu_6(self): self.console.clear() - self.dynamiqueText("Au revoir !","green") - time.sleep(0.04) + self.dynamiqueText("😄​ Merci pour votre visite et à la revoyure 👋​ !","yellow") + time.sleep(2) self.console.clear() - self.console.exit() consoleInterface() From c1c0b228cfbaedd2c2a697046f4996e3c5882096 Mon Sep 17 00:00:00 2001 From: Eunock-web Date: Tue, 5 Aug 2025 03:14:34 +0200 Subject: [PATCH 05/16] Revu des fonctions pour une meilleure optimisation --- src/detecteur_crypto.py | 248 ++++++++++++++++++++++++++++++++-------- 1 file changed, 200 insertions(+), 48 deletions(-) diff --git a/src/detecteur_crypto.py b/src/detecteur_crypto.py index 8e25c99..32a68fb 100644 --- a/src/detecteur_crypto.py +++ b/src/detecteur_crypto.py @@ -1,5 +1,7 @@ # Import des modules import os +import time +from typing import List # Import des modules d'analyse from .analyzers.aes_cbc_analyzer import Aes_Cbc_Analyzer @@ -8,10 +10,13 @@ class ResultatAnalyse: """ Classe représentant un résultat d'analyse. """ - def __init__(self, algo: str, cle: bytes, texte_dechiffre: bytes): + def __init__(self, algo: str, cle: bytes, score_probabilite: float, texte_dechiffre: bytes, temps_execution: float = 0.0, nb_tentatives: int = 0): self.algo = algo self.cle = cle + self.score_probabilite = score_probabilite self.texte_dechiffre = texte_dechiffre + self.temps_execution = temps_execution + self.nb_tentatives = nb_tentatives class DetecteurCryptoOrchestrateur: """ @@ -28,72 +33,219 @@ def __init__(self): self.analyzers = { "AES-CBC": Aes_Cbc_Analyzer(), } + self.missions_completees = [] + self.statistiques_globales = { + "total_fichiers": 0, + "fichiers_dechiffres": 0, + "temps_total": 0.0, + "tentatives_total": 0 + } - def Analyser_fichier_uniquement(self, chemin_fichier_chiffre: str) -> ResultatAnalyse: + def analyser_fichier_specifique(self, chemin_fichier_chiffre: str) -> ResultatAnalyse: """ - Analyse un seul fichier chiffré et retourne le résultat de l'analyse. - - Args: - chemin_fichier_chiffre(str): chemin du fichier chiffré à analyser - - Returns: - ResultatAnalyse: résultat de l'analyse + ANALYSE D'UN FICHIER SPÉCIFIQUE + - Sélection du fichier à analyser + - Identification automatique de l'algorithme + - Affichage des scores de probabilité + + Args: + chemin_fichier_chiffre(str): chemin du fichier chiffré à analyser + + Returns: + ResultatAnalyse: résultat de l'analyse """ + debut_analyse = time.time() + try: - #Initialisation des variables + # Vérification de l'existence du fichier + if not os.path.exists(chemin_fichier_chiffre): + print("Erreur: Fichier non trouvé") + return ResultatAnalyse("", b"", 0.0, b"", 0.0, 0) + + # Initialisation des variables algorithme_detecte = "" cle = b"" + score_probabilite = 0.0 texte_dechiffre = b"" + nb_tentatives = 0 - #Parcours des algorithmes disponibles + # Parcours des algorithmes disponibles + scores_algorithmes = {} for nom_algo, analyzer in self.analyzers.items(): - score_probabilite = analyzer.identifier_algo(chemin_fichier_chiffre) # Retourne un float - print(f"{nom_algo}: score {score_probabilite:.2f}") + score = analyzer.identifier_algo(chemin_fichier_chiffre) + scores_algorithmes[nom_algo] = score + print(f"{nom_algo}: score {score:.2f}") + + if score > 0.5: # Seuil de confiance + algorithme_detecte = nom_algo + score_probabilite = score + print(f"Algorithme détecté: {algorithme_detecte} (score: {score:.2f})") + break + + if not algorithme_detecte: + print("Aucun algorithme coréctement détecté ") + temps_execution = time.time() - debut_analyse + return ResultatAnalyse("", b"", 0.0, b"", temps_execution, nb_tentatives) + + temps_execution = time.time() - debut_analyse + + return ResultatAnalyse(algorithme_detecte, cle, score_probabilite, texte_dechiffre, temps_execution, nb_tentatives) + + except Exception as e: + print(f"Erreur lors de l'analyse: {str(e)}") + temps_execution = time.time() - debut_analyse + return ResultatAnalyse("", b"", 0.0, b"", temps_execution, 0) + + def mission_complete_automatique(self, dossier_chiffres: str) -> List[ResultatAnalyse]: + """ + MISSION COMPLÈTE AUTOMATIQUE + - Analyse des 5 fichiers séquentiellement + - Tentatives de déchiffrement avec retour visuel + - Rapport de synthèse final + + Args: + dossier_chiffres(str): dossier contenant les fichiers chiffrés + + Returns: + list[ResultatAnalyse]: liste des résultats d'analyse + """ + + debut_mission = time.time() + resultats = [] + + try: + # Récupération des fichiers .enc + fichiers_enc = [f for f in os.listdir(dossier_chiffres) if f.endswith(".enc")] + + if not fichiers_enc: + print("Aucun fichier .enc trouvé dans le dossier") + return [] + + print(f"{len(fichiers_enc)} fichiers .enc détectés") + print("\nANALYSE SÉQUENTIELLE DES FICHIERS") + + for i, fichier in enumerate(fichiers_enc, 1): + print(f"\nFICHIER {i}/{len(fichiers_enc)}: {fichier}") - if score_probabilite > 0.5: # Comparaison correcte avec le seuil - algorithme_detecte = nom_algo # Stockage du nom de l'algorithme - print(f"Algorithme détecté: {algorithme_detecte} (score: {score_probabilite:.2f})") + chemin_fichier = os.path.join(dossier_chiffres, fichier) + + # Analyse du fichier + resultat = self.analyser_fichier_specifique(chemin_fichier) + + # Tentative de déchiffrement si algorithme détecté + if resultat.algo: + print(f"\nTENTATIVE DE DÉCHIFFREMENT") - # Génération des clés candidates + analyzer = self.analyzers[resultat.algo] cles_candidates = analyzer.generer_cles_candidates("dicoEn") - print(f"{len(cles_candidates)} clés candidates générées") - # Test de déchiffrement avec la première clé (pour l'exemple) if cles_candidates: - texte_dechiffre = analyzer.dechiffrer(chemin_fichier_chiffre, cles_candidates[0]) - if texte_dechiffre: - cle = cles_candidates[0] - print("Déchiffrement réussi avec la première clé!") + print(f"Test de {len(cles_candidates)} clés candidates...") + + for j, cle in enumerate(cles_candidates): + resultat.nb_tentatives += 1 + + if j % 100 == 0: # retour visuel tous les 100 essais + print(f" Tentative {j+1}/{len(cles_candidates)}...") + + texte_dechiffre = analyzer.dechiffrer(chemin_fichier, cle) + if texte_dechiffre and len(texte_dechiffre) > 0: + resultat.cle = cle + resultat.texte_dechiffre = texte_dechiffre + print(f" Clé trouvée après {j+1} tentatives!") + break else: - print("Déchiffrement échoué avec la première clé") - break + print(" Aucune clé valide trouvée") + else: + print(" Aucune clé candidate générée") + + resultats.append(resultat) + + # retour visuel + if resultat.algo: + print(f"{fichier}: {resultat.algo} (score: {resultat.score_probabilite:.2f})") + else: + print(f"{fichier}: Aucun algorithme détecté") - if not algorithme_detecte: - print("Aucun algorithme détecté avec confiance suffisante") + # Rapport de synthèse final + self.generer_rapport_synthese(resultats, time.time() - debut_mission) - return ResultatAnalyse(algorithme_detecte, cle, texte_dechiffre) - except Exception as e: - print(f"Erreur lors de l'analyse du fichier {chemin_fichier_chiffre}: {str(e)}") - return ResultatAnalyse("", b"", b"") - - - def Analyser_fichiers_sequentiels(self, dossier_chiffres: str) -> list[ResultatAnalyse]: - """ - Analyse plusieurs fichiers chiffrés dans un dossier et retourne les résultats de l'analyse. + # Mise à jour des statistiques globales + self.missions_completees.append({ + "dossier": dossier_chiffres, + "resultats": resultats, + "temps_total": time.time() - debut_mission + }) - Args: - dossier_chiffres(str): dossier contenant les fichiers chiffrés à analyser + return resultats - Returns: - list[ResultatAnalyse]: liste des résultats d'analyse pour chaque fichier + except Exception as e: + print(f"Erreur lors de la mission complète: {str(e)}") + return [] + + def attaque_dictionnaire_manuelle(self, chemin_fichier: str, algorithme_choisi: str) -> ResultatAnalyse: + """ + ATTAQUE PAR DICTIONNAIRE MANUELLE + - Choix du fichier et de l'algorithme + - Suivi en temps réel des tentatives + - Affichage des résultats intermédiaires + + Args: + chemin_fichier(str): chemin du fichier à attaquer + algorithme_choisi(str): algorithme à utiliser + + Returns: + ResultatAnalyse: résultat de l'attaque """ + + + debut_attaque = time.time() + try: - resultats = [] - for fichier_chiffre in os.listdir(dossier_chiffres): - chemin_fichier_chiffre = os.path.join(dossier_chiffres, fichier_chiffre) - resultat = self.Analyser_fichier_uniquement(chemin_fichier_chiffre) - resultats.append(resultat) - return resultats + if algorithme_choisi not in self.analyzers: + print(f"Algorithme {algorithme_choisi} non disponible") + return ResultatAnalyse("", b"", 0.0, b"", 0.0, 0) + + analyzer = self.analyzers[algorithme_choisi] + + # Vérification de l'algorithme + score = analyzer.identifier_algo(chemin_fichier) + print(f"Score de confirmation: {score:.2f}") + + if score < 0.3: + print("Score de confiance faible pour cet algorithme") + + # Génération des clés candidates + print(f"Génération des clés candidates") + cles_candidates = analyzer.generer_cles_candidates("dicoEn") + print(f"{len(cles_candidates)} clés candidates générées") + + # Attaque par dictionnaire + + cle_trouvee = b"" + texte_dechiffre = b"" + nb_tentatives = 0 + + for i, cle in enumerate(cles_candidates): + nb_tentatives += 1 + + # retour visuel en temps réel + if i % 50 == 0: + print(f"Tentative {i+1}/{len(cles_candidates)}... ({(i+1)/len(cles_candidates)*100:.1f}%)") + texte_dechiffre = analyzer.dechiffrer(chemin_fichier, cle) + if texte_dechiffre and len(texte_dechiffre) > 0: + cle_trouvee = cle + break + else: + print(f"Aucune clé valide trouvée après {len(cles_candidates)} tentatives") + + temps_execution = time.time() - debut_attaque + print(f"Temps d'exécution: {temps_execution:.2f} secondes") + + return ResultatAnalyse(algorithme_choisi, cle_trouvee, score, texte_dechiffre, temps_execution, nb_tentatives) + except Exception as e: - print(f"Erreur lors de l'analyse des fichiers: {str(e)}") - return [] \ No newline at end of file + print(f"Erreur lors de l'attaque: {str(e)}") + temps_execution = time.time() - debut_attaque + return ResultatAnalyse("", b"", 0.0, b"", temps_execution, 0) + From b74715c5779696ed05345d7060984bfdd3baf78d Mon Sep 17 00:00:00 2001 From: wesley-kami Date: Tue, 5 Aug 2025 16:26:16 +0100 Subject: [PATCH 06/16] Ajout du guide d'utilisation --- guideUtilisation.txt | 15 ++++++++++ src/interface_console.py | 62 +++++++++++++++++++++++++++++++++++----- 2 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 guideUtilisation.txt diff --git a/guideUtilisation.txt b/guideUtilisation.txt new file mode 100644 index 0000000..e4451cd --- /dev/null +++ b/guideUtilisation.txt @@ -0,0 +1,15 @@ +## **Algorithmes déployés lors des mission** +**AES-256** : +###### 1. **Hello Word** : Ceci est un exemple veuillez suivre ce format pour la documentation de vos algorithmes + +**Chacha20** : +###### 1. **Hello Word** : Ceci est un exemple veuillez suivre ce format pour la documentation de vos algorithmes + +**Blowfish** : +###### 1. **Hello Word** : Ceci est un exemple veuillez suivre ce format pour la documentation de vos algorithmes + +**AES-GCM** : +###### 1. **Hello Word** : Ceci est un exemple veuillez suivre ce format pour la documentation de vos algorithmes + +**Fernet** : +###### 1. **Hello Word** : Ceci est un exemple veuillez suivre ce format pour la documentation de vos algorithmes diff --git a/src/interface_console.py b/src/interface_console.py index fee6eb5..205140b 100644 --- a/src/interface_console.py +++ b/src/interface_console.py @@ -2,7 +2,9 @@ from rich.traceback import install from rich.markdown import Markdown from rich import print +from rich.text import Text from rich.prompt import Prompt +from rich.table import Table # from detecteur_crypto import Analyser_fichier_uniquement # from detecteur_crypto import Analyser_fichier_sequentiels import time, os @@ -66,10 +68,6 @@ def default_menu(self): self.menu_5() elif choix == "6": self.menu_6() - - while choix > "6" or choix < "1": - self.console.print("Veuillez entrer un nombre entre 1 et 6") - choix = self.prompt.ask("Veuillez choisir une option ",choices=["1","2","3","4","5","6"]) except ValueError: self.console.print("Veuillez entrer un nombre entre 1 et 6") except Exception as e: @@ -127,8 +125,58 @@ def menu_4(self): def menu_5(self): self.console.clear() self.dynamiqueText("Système d'aide intégré","green") - time.sleep(0.04) - self.default_menu() + title = Markdown("# Guide d'utilisation",style="yellow bold") + contexte_title = Markdown("### 📋 Contexte de la Mission",style="green") + contexte= Markdown("### Vous êtes un analyste en cybersécurité travaillant pour une agence gouvernementale. Lors d'une opération d'investigation, votre équipe a intercepté 5 fichiers chiffrés contenant des informations cruciales. Votre mission est d'identifier l'algorithme de chiffrement utilisé pour chaque fichier, de découvrir la clé de déchiffrement, puis d'extraire le contenu secret.\n" \ + "### Les criminels ont utilisé 5 algorithmes de chiffrement symétrique différents pour protéger leurs communications. Votre expertise en cryptanalyse sera mise à l'épreuve pour déchiffrer ces messages et découvrir les secrets qu'ils contiennent.\n") + + mission_table = Table(title = "Missions Accomplies",style="",show_lines= True,leading=1) + mission_table.add_column("Intitulé",style="violet",justify="center") + mission_table.add_column("Fichier cible",style="red",justify="center") + mission_table.add_column('Indice',style="yellow",justify="center") + mission_table.add_column("Défi",style="green",justify="center") + + mission_table.add_row("AES-256-CBC","mission1.enc","La clé est liée à une ville française célèbre et une année olympique"," Identifier l'algorithme AES en mode CBC et récupérer la clé par attaque dictionnaire") + mission_table.add_row("ChaCha20","mission2.enc","Combinaison d'une année récente et d'un mot de passe anglais commun","Reconnaître le chiffrement de flux moderne ChaCha20") + mission_table.add_row("Blowfish","mission3.enc","Nom d'un algorithme de hachage populaire suivi de chiffres","Détecter l'algorithme Blowfish et ses spécificités") + mission_table.add_row("AES-256-GCM","mission4.enc","Acronyme d'une organisation internationale + année courante","Identifier le mode authentifié GCM et gérer l'authentification") + mission_table.add_row("Fernet","mission5.enc","Phrase française simple encodée, liée à notre domaine d'étude","Reconnaître le format Fernet et sa structure particulière") + + f = open("guideUtilisation.txt",'r') + algo_docs = Markdown(f.read()) + f.close() + + process= Markdown("### Processus d'usage logiciel",style="purple underline") + intro = Markdown("Comme vous l'avez probablement remarqué le menu de ce logiciel est composé de 06 options dont 04 principales :") + usage_guide_1 = Markdown("1. ### Analyse d'un fichier spécifique \n",style="black on white") + analysis_1 = Markdown(" Cette option a pour but de traiter un fichier crypter ( prise en charge des '.enc' exceptionnellement ) afin d'identifier l'algorithme \n\n" \ + " de cryptage qui lui a été appliqué ainsi que le score de probabilité de chaque algorithme de cryptage cité ci-dessus \n\n") + usage_guide_2 = Markdown("2. ### Mission complète automatique \n",style="black on white") + analysis_2 = Markdown(" Cette option permet de traiter les 05 missions de façon séquentielle afin de ressortir de chacune d'entre elle :\n\n" \ + " -la clé de crypatage\n\n" \ + " -le message déchiffrer\n\n" \ + " A la fin des traitement un synthèse finale est générée sur l'état des Test effectué") + + usage_guide_3 = Markdown("3. ### Attaque par dictionnaire manuelle",style="black on white") + analysis_3=Markdown(" En optant pour cette option vous aurez à sélectionner le fichier que vous souhaitez décrypté et par suite l'algorithme de décryptage que vous voudiez appliquer.\n" \ + " Vous aurez dun suivez en tempps réel de l'evolution des tentatives ainsi que l'affichage du résultat obtenu") + + usage_guide_4 = Markdown("4. ### Affichage des rapports \n",style="black on white") + analysis_4 =Markdown(" Cette option vous permettra d'oberver les rapports des différents tests de décryptages effectués au cours de l'utilisation de ce logiciel") + + final = Markdown("# 😁​ Merci d'utiliser notre logiciel 👾​ et bonne continuation ( **Appuyez sur la touche Enter pour retourner au menu principal** )",style="yellow") + + # print(title,contexte_title,contexte,mission_table,algo_docs,process,intro,usage_guide_1,analysis_1,usage_guide_2,analysis_2,usage_guide_3,analysis_3,usage_guide_4,analysis_4,final) + # escape = input('') + guides = [title,contexte_title,contexte,mission_table,algo_docs,process,intro,usage_guide_1,analysis_1,usage_guide_2,analysis_2,usage_guide_3,analysis_3,usage_guide_4,analysis_4,final] + + for guide in guides: + print(guide) + print("\n") + + escape= input('') + if escape != None: + self.default_menu() def menu_6(self): self.console.clear() @@ -136,4 +184,4 @@ def menu_6(self): time.sleep(2) self.console.clear() -consoleInterface() +consoleInterface() \ No newline at end of file From a45afa078bf4035637d4aad33aca92a19c7d08c7 Mon Sep 17 00:00:00 2001 From: wesley-kami Date: Thu, 7 Aug 2025 00:02:11 +0100 Subject: [PATCH 07/16] =?UTF-8?q?mission1=20+=20console=20pr=C3=A9mices?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/detecteur_crypto.py | 1 - src/interface_console.py | 13 ++++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/detecteur_crypto.py b/src/detecteur_crypto.py index 93fb35d..83aca26 100644 --- a/src/detecteur_crypto.py +++ b/src/detecteur_crypto.py @@ -249,4 +249,3 @@ def attaque_dictionnaire_manuelle(self, chemin_fichier: str, algorithme_choisi: print(f"Erreur lors de l'attaque: {str(e)}") temps_execution = time.time() - debut_attaque return ResultatAnalyse("", b"", 0.0, b"", temps_execution, 0) - diff --git a/src/interface_console.py b/src/interface_console.py index 205140b..4ace459 100644 --- a/src/interface_console.py +++ b/src/interface_console.py @@ -7,6 +7,7 @@ from rich.table import Table # from detecteur_crypto import Analyser_fichier_uniquement # from detecteur_crypto import Analyser_fichier_sequentiels +from detecteur_crypto import DetecteurCryptoOrchestrateur import time, os install() @@ -76,16 +77,18 @@ def default_menu(self): def menu_1(self): self.console.clear() self.dynamiqueText("Analyse d'un fichier spécifique","green") - self.dynamiqueText("Veuillez entrer le chemin du fichier :","white") + self.dynamiqueText("Veuillez entrer le chemin du fichier","yellow") + fichier = self.prompt.ask("") time.sleep(0.04) # chemin_fichier = self.prompt.ask("Veuillez entrer le chemin du fichier : ") # resultat = Analyser_fichier_uniquement(chemin_fichier) self.console.clear() - self.dynamiqueText("Analyse en cours...","green") - time.sleep(0.04) - self.console.clear() + # self.dynamiqueText("Analyse en cours...","green") + # time.sleep(0.04) + # self.console.clear() self.dynamiqueText("Analyse terminée","green") - time.sleep(0.04) + self.console.print(DetecteurCryptoOrchestrateur().analyser_fichier_specifique(fichier)) + # time.sleep(0.04) # def menu_2(self): From ced12b268746fb13305a81d53e216ccb31763b85 Mon Sep 17 00:00:00 2001 From: wesley-kami Date: Thu, 7 Aug 2025 14:05:41 +0100 Subject: [PATCH 08/16] test --- main.py | 2 ++ src/detecteur_crypto.py | 2 ++ src/interface_console.py | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/main.py b/main.py index e69de29..e548258 100644 --- a/main.py +++ b/main.py @@ -0,0 +1,2 @@ +from src.detecteur_crypto import DetecteurCryptoOrchestrateur +print(DetecteurCryptoOrchestrateur().analyser_fichier_specifique('data/mission1.enc')) \ No newline at end of file diff --git a/src/detecteur_crypto.py b/src/detecteur_crypto.py index 83aca26..9a354a6 100644 --- a/src/detecteur_crypto.py +++ b/src/detecteur_crypto.py @@ -249,3 +249,5 @@ def attaque_dictionnaire_manuelle(self, chemin_fichier: str, algorithme_choisi: print(f"Erreur lors de l'attaque: {str(e)}") temps_execution = time.time() - debut_attaque return ResultatAnalyse("", b"", 0.0, b"", temps_execution, 0) + +# print(DetecteurCryptoOrchestrateur().analyser_fichier_specifique('data/mission1.enc')) \ No newline at end of file diff --git a/src/interface_console.py b/src/interface_console.py index 4ace459..f36306d 100644 --- a/src/interface_console.py +++ b/src/interface_console.py @@ -7,7 +7,7 @@ from rich.table import Table # from detecteur_crypto import Analyser_fichier_uniquement # from detecteur_crypto import Analyser_fichier_sequentiels -from detecteur_crypto import DetecteurCryptoOrchestrateur +from .detecteur_crypto import DetecteurCryptoOrchestrateur import time, os install() From d18e690b6b1c636cf4989ca6e287d9c47bcb6578 Mon Sep 17 00:00:00 2001 From: wesley-kami Date: Thu, 7 Aug 2025 23:18:56 +0100 Subject: [PATCH 09/16] =?UTF-8?q?finalisation=20de=20l'int=C3=A9gration=20?= =?UTF-8?q?mission1=20+=20console=20plus=20de=20stress?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/detecteur_crypto.py | 8 +++---- src/interface_console.py | 50 +++++++++++++++++++++++++++------------- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/detecteur_crypto.py b/src/detecteur_crypto.py index 9a354a6..4384812 100644 --- a/src/detecteur_crypto.py +++ b/src/detecteur_crypto.py @@ -66,7 +66,7 @@ def analyser_fichier_specifique(self, chemin_fichier_chiffre: str) -> ResultatAn try: # Vérification de l'existence du fichier - if not os.path.exists(chemin_fichier_chiffre): + if not os.path.exists(f"data/{chemin_fichier_chiffre}"): print("Erreur: Fichier non trouvé") return ResultatAnalyse("", b"", 0.0, b"", 0.0, 0) @@ -80,14 +80,14 @@ def analyser_fichier_specifique(self, chemin_fichier_chiffre: str) -> ResultatAn # Parcours des algorithmes disponibles scores_algorithmes = {} for nom_algo, analyzer in self.analyzers.items(): - score = analyzer.identifier_algo(chemin_fichier_chiffre) + score = analyzer.identifier_algo(f"data/{chemin_fichier_chiffre}") scores_algorithmes[nom_algo] = score - print(f"{nom_algo}: score {score:.2f}") + # print(f"{nom_algo}: score {score:.2f}") if score > 0.5: # Seuil de confiance algorithme_detecte = nom_algo score_probabilite = score - print(f"Algorithme détecté: {algorithme_detecte} (score: {score:.2f})") + # print(f"Algorithme détecté: {algorithme_detecte} (score: {score:.2f})") break if not algorithme_detecte: diff --git a/src/interface_console.py b/src/interface_console.py index f36306d..2b54ce6 100644 --- a/src/interface_console.py +++ b/src/interface_console.py @@ -35,7 +35,7 @@ def dynamiqueText(self,text,color): for char in text: self.console.print(f"[{color}]{char}[/{color}]",end='') - time.sleep(0.04) + time.sleep(0.02) self.console.print('\n') @@ -44,7 +44,7 @@ def default_menu(self): self.console.clear() self.dynamiqueText("😈​ Bienvenue sur Forensic je suis Crypto votre assitant IA minimaliste 🤖​ ","green") self.dynamiqueText("En quoi puis-je vous aider ? :","white") - time.sleep(0.04) + time.sleep(0.02) menuTag = Markdown("# Menu",style="blue") menuOption = Markdown("1. #### Analyse d'un fichier spécifique \n" \ "2. #### Mission complète automatique \n" \ @@ -53,7 +53,7 @@ def default_menu(self): "5. #### Système d'aide intégré \n" \ "6. #### Quitter") self.console.print(menuTag,menuOption) - time.sleep(0.04) + time.sleep(0.02) choix = self.prompt.ask("Veuillez choisir une option ",choices=["1","2","3","4","5","6"]) try: @@ -79,51 +79,69 @@ def menu_1(self): self.dynamiqueText("Analyse d'un fichier spécifique","green") self.dynamiqueText("Veuillez entrer le chemin du fichier","yellow") fichier = self.prompt.ask("") - time.sleep(0.04) + time.sleep(0.02) # chemin_fichier = self.prompt.ask("Veuillez entrer le chemin du fichier : ") # resultat = Analyser_fichier_uniquement(chemin_fichier) - self.console.clear() + # self.console.clear() # self.dynamiqueText("Analyse en cours...","green") - # time.sleep(0.04) + # time.sleep(0.02) # self.console.clear() self.dynamiqueText("Analyse terminée","green") - self.console.print(DetecteurCryptoOrchestrateur().analyser_fichier_specifique(fichier)) - # time.sleep(0.04) + data = DetecteurCryptoOrchestrateur().analyser_fichier_specifique(fichier) + print(f"\n[bold]Algorithme détecté[/bold] : [yellow]{data.algo}[/yellow]") + # print(data.cle) + print(f"\n[bold]Score de probabilité[/bold] : [green]{data.score_probabilite}[/green]") + # print(data.texte_dechiffre) + print(f"\n[bold]Temps d'éxécution[/bold] : [green]{round(data.temps_execution,4)}[/green] s") + esc=input("Veuillez appuyer sur la touche entrer pour retrouner au menu principal") + if esc=="": + self.default_menu() + else : self.default_menu() + # print(data.nb_tentatives) + # time.sleep(0.02) # def menu_2(self): self.console.clear() self.dynamiqueText("Mission complète automatique","green") self.dynamiqueText("Veuillez entrer le chemin du dossier :","white") - time.sleep(0.04) + time.sleep(0.02) # chemin_dossier = self.prompt.ask("Veuillez entrer le chemin du dossier : ") self.console.clear() self.dynamiqueText("Mission en cours...","green") - time.sleep(0.04) + time.sleep(0.02) self.console.clear() self.dynamiqueText("Mission terminée","green") - time.sleep(0.04) + time.sleep(0.02) self.default_menu() def menu_3(self): self.console.clear() self.dynamiqueText("Attaque par dictionnaire manuelle","green") self.dynamiqueText("Veuillez entrer le chemin du fichier :","white") - time.sleep(0.04) + time.sleep(0.02) # chemin_fichier = self.prompt.ask("Veuillez entrer le chemin du fichier : ") self.console.clear() self.dynamiqueText("Attaque en cours...","green") - time.sleep(0.04) + time.sleep(0.02) self.console.clear() self.dynamiqueText("Attaque terminée","green") - time.sleep(0.04) + time.sleep(0.02) self.default_menu() def menu_4(self): self.console.clear() self.dynamiqueText("Affichage des rapports","green") - time.sleep(0.04) - self.default_menu() + time.sleep(0.02) + f = open("rapport_mission.txt",'r') + rapports = f.read() + for rapport in rapports: + print(f"\n{rapport}") + f.close() + esc = input('Veuillez appuyez sur la touche entrer pour continuer') + if esc=='': + self.default_menu() + else: self.default_menu() def menu_5(self): self.console.clear() From 880d922534e695ba1342ec5c9b296b6891d8cda9 Mon Sep 17 00:00:00 2001 From: e-mandy Date: Fri, 8 Aug 2025 21:32:51 +0100 Subject: [PATCH 10/16] =?UTF-8?q?Int=C3=A9gration=20de=20l'AesGcmAnalyzer?= =?UTF-8?q?=20dans=20l'orchestrateur?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/detecteur_crypto.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/detecteur_crypto.py b/src/detecteur_crypto.py index cab72aa..3dd1f5a 100644 --- a/src/detecteur_crypto.py +++ b/src/detecteur_crypto.py @@ -8,6 +8,7 @@ from crypto_analyzer import CryptoAnalyzer from analyzers.chacha20_analyzer import ChaCha20_Analyzer from analyzers.blowfish_analyzer import Blowfish_Analyzer +from analyzers.aes_gcm_analyzer import Aes_Gcm_Analyzer # Import des modules utilitaries from utils import est_dechiffre @@ -39,7 +40,8 @@ def __init__(self): self.analyzers: dict[str, CryptoAnalyzer] = { "AES-CBC": Aes_Cbc_Analyzer(), "ChaCha20": ChaCha20_Analyzer(), - "Blowfish": Blowfish_Analyzer() + "Blowfish": Blowfish_Analyzer(), + "AES-GCM": Aes_Gcm_Analyzer() } self.missions_completees: list[dict[str, Union[str, list[ResultatAnalyse], float]]] = [] self.statistiques_globales: dict[str, Union[int, float]] = { From 1bef18c924f02c875bf61da69e5cd7cdee78069f Mon Sep 17 00:00:00 2001 From: e-mandy Date: Fri, 8 Aug 2025 22:08:18 +0100 Subject: [PATCH 11/16] Initialisation des test de l'algo de blowfish --- .../fichiers_pour_tests/mission3_invalide.enc | 0 tests/test_analyzers.py | 19 ++++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 tests/fichiers_pour_tests/mission3_invalide.enc diff --git a/tests/fichiers_pour_tests/mission3_invalide.enc b/tests/fichiers_pour_tests/mission3_invalide.enc new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_analyzers.py b/tests/test_analyzers.py index a7f5379..477f007 100644 --- a/tests/test_analyzers.py +++ b/tests/test_analyzers.py @@ -9,6 +9,7 @@ from src.analyzers.aes_cbc_analyzer import Aes_Cbc_Analyzer from src.analyzers.chacha20_analyzer import ChaCha20_Analyzer +from src.analyzers.blowfish_analyzer import Blowfish_Analyzer class AesCbcAnalyzerTester(TestCase): @@ -103,7 +104,23 @@ def test_chacha20_dechiffrer_fichier_non_existant(self): cle_valide = self.cle_test_chacha with self.assertRaises(FileNotFoundError): self.analyser_chacha.dechiffrer("chemin_invalide.enc", cle_valide) - + + +class BlowfishAnalyzerTester(TestCase): + + """ + Cette classe contient les différents tests éffectués sur les méthodes en rapport avec l'analyzer Blowfish + """ + + def setUp(self): + self.fichier_crypte_invalide = "./tests/fichiers_pour_tests/mission3_invalide.enc" + + self.analyzer = Blowfish_Analyzer() + + def test_identifier_algo(self): + self.assertAlmostEqual(self.analyzer.identifier_algo(self.fichier_crypte_invalide), 0) + self.assertAlmostEqual(self.analyzer.identifier_algo()) + if __name__ == '__main__': main() \ No newline at end of file From 87b58cd6b6b923b49fb3f566ed4d8149b233db35 Mon Sep 17 00:00:00 2001 From: e-mandy Date: Sat, 9 Aug 2025 04:39:16 +0100 Subject: [PATCH 12/16] Mise en place des tests unitaires en rapport avec l'analyzer Blowfish --- src/analyzers/blowfish_analyzer.py | 16 ++++++-- src/utils.py | 2 +- tests/fichiers_pour_tests/mission3_valide.enc | Bin 0 -> 64 bytes tests/test_analyzers.py | 37 +++++++++++++++--- 4 files changed, 45 insertions(+), 10 deletions(-) create mode 100644 tests/fichiers_pour_tests/mission3_valide.enc diff --git a/src/analyzers/blowfish_analyzer.py b/src/analyzers/blowfish_analyzer.py index 8188db5..47da863 100644 --- a/src/analyzers/blowfish_analyzer.py +++ b/src/analyzers/blowfish_analyzer.py @@ -1,8 +1,11 @@ -from ..detecteur_crypto import CryptoAnalyzer +import sys +import os from ..utils import calculer_entropie import hashlib +from src.crypto_analyzer import CryptoAnalyzer from cryptography.hazmat.primitives.ciphers import algorithms, Cipher, modes from cryptography.hazmat.primitives.padding import PKCS7 +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) class Blowfish_Analyzer(CryptoAnalyzer): '''Détermine si l'algo blowfish est utilisé, génère des clés et tente de de déchffrer un fichier chiffré en utilisant les clés générées. @@ -47,9 +50,10 @@ def identifier_algo(self, chemin_fichier_chiffre: str) -> float: score += 0.4 donnees_chiffrees = contenu_fichier[TAILLE_IV:] - + # Heuristique 2 : Vérification de l'entropie globale entropie_globale = calculer_entropie(donnees_chiffrees) + print(entropie_globale) if entropie_globale > 7.5: score += 0.3 @@ -62,6 +66,8 @@ def identifier_algo(self, chemin_fichier_chiffre: str) -> float: if entropie_moitie1 > 7.5 and entropie_moitie2 > 7.5: score += 0.3 + else: + print(score) except FileNotFoundError: return 0.0 @@ -115,7 +121,9 @@ def generer_cles_candidates(self, chemin_dictionnaire: str) -> list[bytes]: cles_candidates: list[bytes] = [] # Utilisation de la méthode privée pour filtrer les mots mots_de_passe_cible = self.__filtrer_dictionnaire_par_indice(chemin_dictionnaire) - + + + for mot in mots_de_passe_cible: mot_en_bytes = mot.encode("utf-8") @@ -154,7 +162,7 @@ def dechiffrer(self, chemin_fichier_chiffre: str, cle_donnee: bytes) -> bytes: algorithm_blowfish = algorithms.Blowfish(cle_donnee) texte_chiffre = '' - #Récupération de l'IV et des texte chiffré das le fichier + #Récupération de l'IV et des texte chiffré dans le fichier with open(chemin_fichier_chiffre, 'rb') as f: initialization_vector = f.read(self.__BLOWFISH_TAILLE_IV) texte_chiffre = f.read() diff --git a/src/utils.py b/src/utils.py index 0e481e6..f24aeab 100644 --- a/src/utils.py +++ b/src/utils.py @@ -187,4 +187,4 @@ def rangerDico() -> None: print(compte) except FileNotFoundError: print('Fichier non trouvé.') -# rangerDico() +# rangerDico() \ No newline at end of file diff --git a/tests/fichiers_pour_tests/mission3_valide.enc b/tests/fichiers_pour_tests/mission3_valide.enc new file mode 100644 index 0000000000000000000000000000000000000000..d2cb7172ade9717af1983731086c543ced711257 GIT binary patch literal 64 zcmV-G0Kfmf!v2duY~o{t?D>CR0Ktoc;|G>AKqM2MUpOe-BJ{h{_26Lrf~mvf3Dq{4 WC?}?q?2v5Hal$qxK6Aly*_zvJu_DU= literal 0 HcmV?d00001 diff --git a/tests/test_analyzers.py b/tests/test_analyzers.py index 477f007..0814ff2 100644 --- a/tests/test_analyzers.py +++ b/tests/test_analyzers.py @@ -3,6 +3,8 @@ import sys import hashlib from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305 +from Crypto.Cipher import Blowfish +from struct import pack sys.path.append(os.path.join(os.path.dirname(__file__), '..')) sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..')) @@ -113,14 +115,39 @@ class BlowfishAnalyzerTester(TestCase): """ def setUp(self): - self.fichier_crypte_invalide = "./tests/fichiers_pour_tests/mission3_invalide.enc" - + # Initialisation de la classe Blowfish_Analyzer pour les tests des méthodes de cette dernière self.analyzer = Blowfish_Analyzer() + # Fichier invalide pour les tests d'exceptions et de résultat d'erreur + self.fichier_crypte_invalide = "tests/fichiers_pour_tests/mission3_invalide.enc" + self.fichier_crypte_valide = "tests/fichiers_pour_tests/mission3_valide.enc" + self.fichier_dictionnaire = "./keys/wordlist.txt" + self.key = b'This is 2 blowfish algorithm key' + self.mot_a_trouver = b'zertyuiopqsdfghjklmwxcvbn,;&1234567890iubdo,cap!=)"_' def test_identifier_algo(self): - self.assertAlmostEqual(self.analyzer.identifier_algo(self.fichier_crypte_invalide), 0) - self.assertAlmostEqual(self.analyzer.identifier_algo()) + self.assertAlmostEqual(self.analyzer.identifier_algo(self.fichier_crypte_invalide), 0.0) + self.assertAlmostEqual(self.analyzer.identifier_algo(self.fichier_crypte_valide), 0.7) + + def test_generer_cles_candidates(self): + # Dans ce cas, on a un dictionnaire qui contient des valeurs qui ne cadrent pas + # avec notre fichier de test, donc la génération renverra une liste vide + self.assertNotEqual(self.analyzer.generer_cles_candidates(self.fichier_dictionnaire), []) + + def test_dechiffrer_taille_cle_invalide(self): + # On tente de lever l'exception ValueError en renseignant une clé ne respectant + # l'intervalle pour la taille requise + invalide_key = b'\x00' + with self.assertRaises(ValueError): + self.analyzer.dechiffrer(self.fichier_crypte_valide, invalide_key) - + def test_dechiffrer_fichier_introuvable(self): + # Vérification de l'exception FileNotFoundError + with self.assertRaises(FileNotFoundError): + self.analyzer.dechiffrer('dohi.txt', self.key) + + # def test_dechiffrer_fichier(self): + # # Cas où la valeur de sortie ne correspond à celle attendue + # self.assertNotEqual(self.analyzer.dechiffrer(self.fichier_crypte_valide, self.key), b'Dohi 1 fois') + if __name__ == '__main__': main() \ No newline at end of file From 98be21dc21c5f25a1a3d9f55f31db0661cb800d3 Mon Sep 17 00:00:00 2001 From: e-mandy Date: Sat, 9 Aug 2025 05:03:40 +0100 Subject: [PATCH 13/16] =?UTF-8?q?Correction=20des=20erreurs=20li=C3=A9es?= =?UTF-8?q?=20au=20tests=20unitaires=20de=20l'analyzer=20Blowfish?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/fichiers_pour_tests/mission3_valide.enc | Bin 64 -> 16 bytes tests/test_analyzers.py | 3 +++ 2 files changed, 3 insertions(+) diff --git a/tests/fichiers_pour_tests/mission3_valide.enc b/tests/fichiers_pour_tests/mission3_valide.enc index d2cb7172ade9717af1983731086c543ced711257..5f16393e982c6ec47e2c7c1b93108cc27d82af7a 100644 GIT binary patch literal 16 Ycmex(n^pD0ZLyo0D*pZpYuRQ407Z=lTL1t6 literal 64 zcmV-G0Kfmf!v2duY~o{t?D>CR0Ktoc;|G>AKqM2MUpOe-BJ{h{_26Lrf~mvf3Dq{4 WC?}?q?2v5Hal$qxK6Aly*_zvJu_DU= diff --git a/tests/test_analyzers.py b/tests/test_analyzers.py index 0814ff2..e9f0499 100644 --- a/tests/test_analyzers.py +++ b/tests/test_analyzers.py @@ -146,6 +146,9 @@ def test_dechiffrer_fichier_introuvable(self): self.analyzer.dechiffrer('dohi.txt', self.key) # def test_dechiffrer_fichier(self): + # # Déchiffrement du fichier valide en utilisant la bonne clé + # self.assertEqual(self.analyzer.dechiffrer(self.fichier_crypte_valide, self.key), self.mot_a_trouver) + # # Cas où la valeur de sortie ne correspond à celle attendue # self.assertNotEqual(self.analyzer.dechiffrer(self.fichier_crypte_valide, self.key), b'Dohi 1 fois') From 54e93dcf55daf2919223efe9ce62d6ddf8f59953 Mon Sep 17 00:00:00 2001 From: e-mandy Date: Mon, 11 Aug 2025 10:25:06 +0100 Subject: [PATCH 14/16] Commit 2spi --- src/analyzers/blowfish_analyzer.py | 2 +- src/utils.py | 2 +- tests/test_analyzers.py | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/analyzers/blowfish_analyzer.py b/src/analyzers/blowfish_analyzer.py index 47da863..0b1602b 100644 --- a/src/analyzers/blowfish_analyzer.py +++ b/src/analyzers/blowfish_analyzer.py @@ -21,7 +21,7 @@ class Blowfish_Analyzer(CryptoAnalyzer): ''' __BLOWFISH_TAILLE_BLOC = 8 - __BLOWFISH_TAILLE_IV = 8 + __BLOWFISH_TAILLE_IV = 12 def identifier_algo(self, chemin_fichier_chiffre: str) -> float: ''' diff --git a/src/utils.py b/src/utils.py index f24aeab..bf8f00d 100644 --- a/src/utils.py +++ b/src/utils.py @@ -29,7 +29,7 @@ def calculer_entropie(bytes: bytes) -> float: i += 1 proba_byte = 1 / i - entropie += (proba_byte) * math.log(1/proba_byte, 8) + entropie += (proba_byte) * math.log(1/proba_byte, 2) return entropie diff --git a/tests/test_analyzers.py b/tests/test_analyzers.py index e9f0499..df47228 100644 --- a/tests/test_analyzers.py +++ b/tests/test_analyzers.py @@ -124,9 +124,9 @@ def setUp(self): self.key = b'This is 2 blowfish algorithm key' self.mot_a_trouver = b'zertyuiopqsdfghjklmwxcvbn,;&1234567890iubdo,cap!=)"_' - def test_identifier_algo(self): - self.assertAlmostEqual(self.analyzer.identifier_algo(self.fichier_crypte_invalide), 0.0) - self.assertAlmostEqual(self.analyzer.identifier_algo(self.fichier_crypte_valide), 0.7) + # def test_identifier_algo(self): + # self.assertAlmostEqual(self.analyzer.identifier_algo(self.fichier_crypte_invalide), 0.0) + # self.assertAlmostEqual(self.analyzer.identifier_algo(self.fichier_crypte_valide), 0.7) def test_generer_cles_candidates(self): # Dans ce cas, on a un dictionnaire qui contient des valeurs qui ne cadrent pas @@ -145,12 +145,12 @@ def test_dechiffrer_fichier_introuvable(self): with self.assertRaises(FileNotFoundError): self.analyzer.dechiffrer('dohi.txt', self.key) - # def test_dechiffrer_fichier(self): - # # Déchiffrement du fichier valide en utilisant la bonne clé - # self.assertEqual(self.analyzer.dechiffrer(self.fichier_crypte_valide, self.key), self.mot_a_trouver) + def test_dechiffrer_fichier(self): + # Déchiffrement du fichier valide en utilisant la bonne clé + self.assertEqual(self.analyzer.dechiffrer(self.fichier_crypte_valide, self.key), self.mot_a_trouver) - # # Cas où la valeur de sortie ne correspond à celle attendue - # self.assertNotEqual(self.analyzer.dechiffrer(self.fichier_crypte_valide, self.key), b'Dohi 1 fois') + # Cas où la valeur de sortie ne correspond à celle attendue + self.assertNotEqual(self.analyzer.dechiffrer(self.fichier_crypte_valide, self.key), b'Dohi 1 fois') if __name__ == '__main__': main() \ No newline at end of file From 9fe04a57eb4c008670e12d6d9bc11696b08e117a Mon Sep 17 00:00:00 2001 From: e-mandy Date: Tue, 12 Aug 2025 18:26:41 +0100 Subject: [PATCH 15/16] Ajout de la documentation en rapport avec l'analyzer Blowfish --- src/analyzers/blowfish_analyzer.py | 6 ++++++ tests/fichiers_pour_tests/aes_gcm_invalide.enc | 2 +- tests/fichiers_pour_tests/fernet_invalide.enc | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/analyzers/blowfish_analyzer.py b/src/analyzers/blowfish_analyzer.py index 874d642..823e101 100644 --- a/src/analyzers/blowfish_analyzer.py +++ b/src/analyzers/blowfish_analyzer.py @@ -102,6 +102,12 @@ def __filtrer_dictionnaire_par_indices(self, chemin_dictionnaire: str) -> list[s """ Filtre le dictionnaire en se basant sur les indices de la mission 3. L'indice pointe vers un format de clé "sha + nombre + chiffres simples". + + Args: + chemin_dictionnaire (str): Chemin du dictionnaire sur lequel on effectue la recherche des potentielles mots clés + + Return: + list[str]: La liste de tous les mots en chaine de caractères, susceptibles d'être des mots clés parmi ceux du dictionnaire fourni. """ mots_filtres: list[str] = [] prefixes = ("sha256", "sha384", "sha512", "sha1") diff --git a/tests/fichiers_pour_tests/aes_gcm_invalide.enc b/tests/fichiers_pour_tests/aes_gcm_invalide.enc index 9832b39..ef32f59 100644 --- a/tests/fichiers_pour_tests/aes_gcm_invalide.enc +++ b/tests/fichiers_pour_tests/aes_gcm_invalide.enc @@ -1 +1 @@ -IVkil6q O o^iA)ф@nt7K6SGrGu '_J_bA6> \ No newline at end of file +'yM|L_M1Ģlgb☺c1ޒJ|54{~VGyo \ No newline at end of file diff --git a/tests/fichiers_pour_tests/fernet_invalide.enc b/tests/fichiers_pour_tests/fernet_invalide.enc index 82604d0..4fd6c8a 100644 --- a/tests/fichiers_pour_tests/fernet_invalide.enc +++ b/tests/fichiers_pour_tests/fernet_invalide.enc @@ -1 +1 @@ -gAAAAABomRFQlKp52Rye3Z1vgFS_n2BOoG4C9eY2kCSga8HN_OLs7PcjvvAfbLk1WXOwgk0bs8iUzvOSCmiqKRVeintPVEhQNEEUUU1gcCvaS3QOqdIi2dlFcLruMjlXZ0-bWanXro2HI0813g4NArEggiWYE_si-w== \ No newline at end of file +gAAAAABom3Vp326Xbih5kXNHM7p8DtVSbjlHDHKXyZi9H3ji0DZUMTiSEPnILw_1J3_dB_QJAFeWUbUgT_ZUcf0PmQ2_NgTWH5QHN3_9ChZM2d226RIwSQ_QEttbl9yRBllh-gs8QCs8a8Aw6F7pZl3wRf8wuHM2Yg== \ No newline at end of file From b51a6dea3145748b1a10ffc01aab9e0409e3d6e6 Mon Sep 17 00:00:00 2001 From: e-mandy Date: Wed, 13 Aug 2025 00:18:25 +0100 Subject: [PATCH 16/16] New interface 2 --- src/interface_console.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/interface_console.py b/src/interface_console.py index 7f46af8..24d27fe 100644 --- a/src/interface_console.py +++ b/src/interface_console.py @@ -112,8 +112,12 @@ def menu_2(self): self.dynamiqueText("Mission complète automatique","green") self.dynamiqueText("Veuillez entrer le chemin du dossier :","white") time.sleep(0.02) - - chemin_dossier = self.prompt.ask("Veuillez entrer le chemin du dossier : ") + pad = 0 + while pad < self.calc_center("data"): + print(" ",end='') + pad+=1 + + chemin_dossier = self.prompt.ask("") resultat = DetecteurCryptoOrchestrateur().mission_complete_automatique(chemin_dossier, "keys/wordlist.txt") print(line for line in resultat) # self.console.clear() @@ -121,15 +125,13 @@ def menu_2(self): time.sleep(0.02) # self.console.clear() self.dynamiqueText("Mission terminée","green") - + esc=input("Veuillez appuyer sur la touche entrer pour retourner au menu principal") time.sleep(0.02) - + if esc=="": self.default_menu() else : self.default_menu() - - # self.default_menu() def menu_3(self): self.console.clear()