Skip to content

Commit 5b60330

Browse files
seathiel-12e-mandymouwaficbdr
authored
Feature/progress bar (#49)
* Documentation de la fonction d'entropie * Essai de fusion (1/2) * Implementation de la fonction de validation du texte déchiffrer * Récupération du main (1/2) * Mise en place des tests unitaires (1/4) * Revert "Mise en place des tests unitaires (1/4)" This reverts commit e965801. * Mise en place des tests unitaires (1/4) * Définition de la classe de gestion des rapports de ission et implémentatioon de la fonction de génération des rapport de synthèse * Implémentation de la fonction de recherche d'anciens rapports * Mise en place des tests liés à l'analyzer aes cbc * Corrections de typage et de logique * Correction du comportement à la levée de l'exception * Correction de la lgoque de test de test_exception_déchiffrer * Corection de la logique de test_verification_texte_dechiffre * fix: Utilisation de pathlib pour une gestion portable des chemins. * merge réussi * Validation des tests et corrections du rapport mission * chekpoint: Blowfish _Analyzer.identifier_algo() * add: Intiialisation de Blowfish_Analyzer et implémentation de Blowfish_Analyzer.identifier_algo() * Implémentation de Blowfish_Analyzer.filtrer_dictionnaire_par_indice() * Correction de bug * Implementer de Blowfish déchiffrer * Integration de blowfish dans le detecteur crypto * Gestion des bugs de chemin et d'import * Update gitignore * add: Fichier run_tests.py qui run tous les tests et donne le feedback * fix: Standardisation uniforme de tous les imports pour uniformité * tests aes_gcm * fix: Correction de la validation de la taille de clé dans Blowfish_Analyzer pour respecter l'intervalle de 4 à 56 bytes. * fix: Amélioration et uniformisation de la gestion des erreurs pour les différents cas. * fix: Correction des erreurs de logique * merged * test de l'analyzer Fernet * Correction de l'orchestrateur et ajustements correspondants * Lancement du système de stepping pour la progress bar * fix: Corrections mineures * Integration de la progress bar et correction correspondantes --------- Co-authored-by: e-mandy <andymfrd02@gmail.com> Co-authored-by: Let Me Cook <badaroumouwafic@gmail.com>
1 parent ec71247 commit 5b60330

File tree

6 files changed

+189
-96
lines changed

6 files changed

+189
-96
lines changed

main.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
import sys
2+
import time
13
from src.detecteur_crypto import DetecteurCryptoOrchestrateur, ResultatAnalyse
24
from src.analyzers.blowfish_analyzer import Blowfish_Analyzer
35
from src.analyzers.aes_cbc_analyzer import Aes_Cbc_Analyzer
46
from src.interface_console import consoleInterface
57
import os
8+
from rich.progress import track
69
# print(DetecteurCryptoOrchestrateur().analyser_fichier_specifique('data/mission1.enc'))
710

811
# try:
@@ -14,4 +17,5 @@
1417
# print("Erreur: Le fichier 'mission3.enc' est introuvable.")
1518

1619
consoleInterface()
17-
# print(DetecteurCryptoOrchestrateur().mission_complete_automatique('data/', 'keys/wordlist.txt'))
20+
# print(DetecteurCryptoOrchestrateur().mission_complete_automatique('data/', 'keys/wordlist.txt'))
21+

rapport_mission.txt

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

requirements.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@ cffi==1.17.1
22
cryptography==43.0.0
33
pycparser==2.22
44
pycryptodome==3.23.0
5-
rich==14.1.0
5+
rich==14.1.0
6+
tqdm==4.67.1
7+
colorama==0.4.6

src/detecteur_crypto.py

Lines changed: 152 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@
1111
from src.analyzers.aes_gcm_analyzer import Aes_Gcm_Analyzer
1212
from src.analyzers.fernet_analyzer import FernetAnalyzer
1313
from src.rapport_mission import rapport_mission
14-
1514
# Import des modules utilitaries
1615
from src.utils import verifier_texte_dechiffre
17-
16+
from rich.progress import Progress
17+
from rich.markdown import Markdown
18+
from rich.console import Console
1819
class ResultatAnalyse:
1920
"""
2021
Classe représentant un résultat d'analyse.
@@ -36,6 +37,9 @@ class DetecteurCryptoOrchestrateur:
3637
-Lance et coordonnes le processus de dechiffrement
3738
"""
3839

40+
_NBR_OPERATION_MISSION = 4
41+
_NBR_OPERATION_ANALYSE = 3
42+
3943
def __init__(self):
4044
"""
4145
Initialisation de tous les modules d'analyse disponibles
@@ -55,7 +59,7 @@ def __init__(self):
5559
"tentatives_total": 0
5660
}
5761

58-
def analyser_fichier_specifique(self, chemin_fichier_chiffre: str) -> ResultatAnalyse:
62+
def analyser_fichier_specifique(self, chemin_fichier_chiffre: str, progress : Progress, task, error:bool, nbr_opr_mission: int) -> ResultatAnalyse:
5963
"""
6064
ANALYSE D'UN FICHIER SPÉCIFIQUE
6165
- Sélection du fichier à analyser
@@ -64,21 +68,32 @@ def analyser_fichier_specifique(self, chemin_fichier_chiffre: str) -> ResultatAn
6468
6569
Args:
6670
chemin_fichier_chiffre(str): chemin du fichier chiffré à analyser
67-
71+
progress (Progress) : la progress bar à mettre à jour
72+
error(bool): nécessaire pour déterminer les erreurs et définir le message de final de la progress bar
6873
Returns:
6974
ResultatAnalyse: résultat de l'analyse
7075
"""
7176
debut_analyse = time.time()
7277

7378
try:
7479
# Vérification de l'existence du fichier
75-
time.sleep(0.3) # TODO : Intégrer la progress bar -> step : Verification du chemin de fichier fourni
80+
avance = (100/(self._NBR_OPERATION_ANALYSE * nbr_opr_mission))
81+
time.sleep(0.3) # Done : Intégrer la progress bar -> step : Verification du chemin de fichier fourni
82+
progress.update(task_id=task, description="Verification du chemin de fichier fourni", advance=avance * 0.3)
83+
time.sleep(1)
84+
7685
if not os.path.isfile(Path('data')/f"{chemin_fichier_chiffre}"):
77-
print("Erreur: Fichier non trouvé")
86+
time.sleep(0.3) # TODO : Intégrer la progress bar -> step : Verification du chemin de fichier fourni
87+
progress.update(task_id=task, description="Fichier non trouvé ❌ (Aborting...)", advance=((avance * self._NBR_OPERATION_ANALYSE) - avance * 0.3) )
88+
time.sleep(1)
89+
error = True
7890
return ResultatAnalyse("", b"", 0.0, b"", 0.0, 0)
7991

8092
# Initialisation des variables
8193
time.sleep(0.5) # TODO : Mise à jour de la progress bar -> step : Initialisation des utilitaires pour l'identification
94+
progress.update(task_id=task, description="Initialisation des utilitaires pour l'identification", advance=avance*0.2)
95+
time.sleep(1)
96+
8297
algorithme_detecte = ""
8398
cle = b""
8499
score_probabilite = 0.0
@@ -87,22 +102,39 @@ def analyser_fichier_specifique(self, chemin_fichier_chiffre: str) -> ResultatAn
87102

88103
# Parcours des algorithmes disponibles
89104
scores_algorithmes = {}
105+
106+
# Pour les arrêts en cas d'erreurs, servira à upgrade la progress bar
107+
cumul_progress_avance = 0
108+
90109
for nom_algo, analyzer in self.analyzers.items():
110+
avance_algo = avance/(len(self.analyzers)*3 * 0.5)
91111
time.sleep(0.5) # TODO : Mise à jour de la progress bar -> step : Utilisation de {algrorithme} pour déterminer le chiffrement
92-
112+
progress.update(task_id=task, description=f"Utilisation de {nom_algo} pour déterminer le chiffrement", advance=avance_algo)
113+
time.sleep(1)
114+
93115
score = analyzer.identifier_algo(f"data/{chemin_fichier_chiffre}")
94116
scores_algorithmes[nom_algo] = score
117+
95118
time.sleep(0.5) # TODO : Mise à jour de la progress bar -> step : Analyse des résultats d'identification
96-
# print(f"{nom_algo}: score {score:.2f}")
119+
progress.update(task_id=task, description="Analyse des résultats d'identification", advance=avance_algo)
120+
time.sleep(1)
121+
122+
cumul_progress_avance += 2 * avance_algo
97123

98124
if score > 0.9 : # Seuil de confiance
99125
time.sleep(1) # TODO : Mise à jour de la progress bar -> step : Détection réussie pour {algorithme} et préparation du rapport d'analyse
126+
progress.update(task_id=task, description=f"Détection réussie pour {nom_algo} et préparation du rapport d'analyse", advance=((100/nbr_opr_mission) - cumul_progress_avance))
127+
time.sleep(1)
128+
100129
algorithme_detecte = nom_algo
101130
score_probabilite = score
102-
# print(f"Algorithme détecté: {algorithme_detecte} (score: {score:.2f})")
103131
break
104132
else :
105-
pass # TODO : Intégrer la progress bar -> step : Echec d'identification pour {algorithme}
133+
time.sleep(1) # TODO : Intégrer la progress bar -> step : Echec d'identification pour {algorithme}
134+
progress.update(task_id=task, description=f"Echec d'identification pour {nom_algo}", advance=avance_algo)
135+
time.sleep(1)
136+
cumul_progress_avance += avance_algo
137+
106138
if not algorithme_detecte:
107139
print("Aucun algorithme correctement détecté ")
108140
temps_execution = time.time() - debut_analyse
@@ -115,15 +147,25 @@ def analyser_fichier_specifique(self, chemin_fichier_chiffre: str) -> ResultatAn
115147
except Exception as e:
116148
print(f"Erreur lors de l'analyse: {str(e)}")
117149
temps_execution = time.time() - debut_analyse
150+
error = True
118151
return ResultatAnalyse("", b"", 0.0, b"", temps_execution, 0, chemin_fichier_chiffre)
119152

120153
def __tenter_dechiffrement_avec_dictionnaire(self, chemin_fichier: str, cles_candidates: list[bytes], analyzer: CryptoAnalyzer, resultat: ResultatAnalyse):
154+
"""
155+
Tente de déchiffrer un fichier avec les clés candidates et l'analyzer correspondant
156+
157+
Args:
158+
chemin_fichier(str) : chemin vers le fichier
159+
cles_candidates(list[bytes]) : les clés candidates retenus par le dossier de clés sur la base des indices
160+
analyzer(CryptoAnalyzer) : l'Analyzer correspondant à ce fichier
161+
resultat(ResultatAnalyse) : les résultats de l'analyse de fichier
162+
163+
Returns :
164+
bool : si une erreur est survenue ou non
165+
"""
121166
for j, cle in enumerate(cles_candidates):
122167
resultat.nb_tentatives += 1
123-
124-
if j % 100 == 0: # retour visuel tous les 100 essais
125-
print(f"Tentative {j+1}/{len(cles_candidates)}...")
126-
168+
127169
texte_dechiffre = analyzer.dechiffrer(chemin_fichier, cle).decode('utf-8')
128170
succes = verifier_texte_dechiffre(texte_dechiffre)['taux_succes']
129171

@@ -132,9 +174,10 @@ def __tenter_dechiffrement_avec_dictionnaire(self, chemin_fichier: str, cles_can
132174
resultat.texte_dechiffre = texte_dechiffre
133175
resultat.taux_succes = succes
134176
print(f"Clé trouvée après {j+1} tentatives!")
135-
return
177+
return False
136178

137179
print("Aucune clé valide trouvée")
180+
return True
138181

139182
def mission_complete_automatique(self, dossier_chiffres: str, chemin_dictionnaire: str) -> List[ResultatAnalyse]:
140183
"""
@@ -152,75 +195,113 @@ def mission_complete_automatique(self, dossier_chiffres: str, chemin_dictionnair
152195

153196
debut_mission = time.time()
154197
resultats: list[ResultatAnalyse] = []
155-
156198
try:
157-
# Récupération des fichiers .enc
158-
fichiers_enc = [f for f in os.listdir(dossier_chiffres) if f.endswith(".enc")]
159-
160-
if not fichiers_enc:
161-
print("Aucun fichier .enc trouvé dans le dossier")
162-
return []
163-
164-
print(f"{len(fichiers_enc)} fichiers .enc détectés")
165-
print("\nANALYSE SÉQUENTIELLE DES FICHIERS")
166-
167-
for i, fichier in enumerate(fichiers_enc, 0):
168-
169-
print(f"\nFICHIER {i+1}/{len(fichiers_enc)}: {fichier}")
170-
171-
chemin_fichier = os.path.join(dossier_chiffres, fichier)
199+
with Progress() as progress :
200+
# Récupération des fichiers .enc
201+
fichiers_enc = [f for f in os.listdir(dossier_chiffres) if f.endswith(".enc")]
172202

173-
# Analyse du fichier
174-
resultat = self.analyser_fichier_specifique(fichier)
203+
if not fichiers_enc:
204+
print("Aucun fichier .enc trouvé dans le dossier")
205+
return []
175206

176-
# Tentative de déchiffrement si algorithme détecté
177-
if resultat.algo:
178-
print(f"\nTENTATIVE DE DÉCHIFFREMENT")
207+
print(f"{len(fichiers_enc)} fichiers .enc détectés")
208+
print("\nANALYSE SÉQUENTIELLE DES FICHIERS")
209+
time.sleep(0.5)
210+
for i, fichier in enumerate(fichiers_enc, 0):
211+
print(f"\nFICHIER {i+1}/{len(fichiers_enc)}: {fichier}")
212+
213+
# TODO: New progress bar -> step: Analyse du fichier mission{i+1}.enc
214+
task = progress.add_task(f"Analyse du fichier mission{i+1}.enc...", total=100)
215+
time.sleep(0.5)
216+
217+
chemin_fichier = os.path.join(dossier_chiffres, fichier)
218+
219+
# Analyse du fichier
220+
error = False
221+
resultat = self.analyser_fichier_specifique(fichier, progress, task, error, self._NBR_OPERATION_MISSION)
222+
223+
# Tentative de déchiffrement si algorithme détecté
224+
if resultat.algo:
225+
# TODO: MAJ de la progress bar -> step: Amorçage de la phase de déchiffrement
226+
progress.update(task, description="Amorçage de la phase de déchiffrement...", advance=((100/self._NBR_OPERATION_MISSION) * 0.5))
227+
time.sleep(1)
228+
229+
analyzer = self.analyzers[resultat.algo]
230+
231+
# TODO: MAJ de la progress bar -> step: Récupération des clés candidates
232+
progress.update(task, description="Récupération des clés candidates", advance=(100/self._NBR_OPERATION_MISSION)*0.5)
233+
time.sleep(1)
234+
235+
cles_candidates = analyzer.generer_cles_candidates(chemin_dictionnaire)
236+
237+
if cles_candidates:
238+
print(f"Test de {len(cles_candidates)} clés candidates...")
239+
# TODO: MAJ de la progress bar -> step: Test de déchiffrement
240+
progress.update(task, description="Test de déchiffrement", advance=(100/self._NBR_OPERATION_MISSION))
241+
time.sleep(3)
242+
243+
error = self.__tenter_dechiffrement_avec_dictionnaire(chemin_fichier, cles_candidates, analyzer, resultat)
244+
245+
else:
246+
# TODO: MAJ de la progress bar -> step: Abort et récupération des résultats d'analyse
247+
progress.update(task, description="Aucune clé candidate générée ❌ (Aborting ...)", advance=(100/self._NBR_OPERATION_MISSION))
248+
time.sleep(3)
249+
error = True
250+
179251

180-
analyzer = self.analyzers[resultat.algo]
181-
cles_candidates = analyzer.generer_cles_candidates(chemin_dictionnaire)
252+
resultats.append(resultat)
182253

183-
if cles_candidates:
184-
print(f"Test de {len(cles_candidates)} clés candidates...")
254+
# retour visuel
255+
if resultat.algo:
256+
# TODO: MAJ de la progress bar -> step: Finalsation et retour de résultats
257+
progress.update(task, description="Finalisation et retour des résultats", advance=(100/self._NBR_OPERATION_MISSION))
258+
time.sleep(3)
185259

186-
self.__tenter_dechiffrement_avec_dictionnaire(chemin_fichier, cles_candidates, analyzer, resultat)
260+
print(f"{fichier}: {resultat.algo} (score: {resultat.score_probabilite:.2f})")
261+
262+
message = "[bold green] Mission terminée. ✅[/bold green]\n\n" if not error else "[bold red] Mission terminée: Déchiffrement non concluant. ❌ [/bold red]\n\n"
263+
Console().print(message)
187264
else:
188-
print(" Aucune clé candidate générée")
265+
progress.update(task, description="Aborting et récupération des résultats d'analyse...", advance=100)
266+
time.sleep(0.5) # TODO: MAJ de la progress bar -> step: Abort et récupération des résultats d'analyse
267+
Console().print(f"[bold yellow] Mission terminée: Aucun algorithme détecté. ⚠️[/bold yellow]\n\n")
268+
269+
progress.remove_task(task)
189270

190-
resultats.append(resultat)
271+
# Rapport de synthèse final
272+
with Progress() as progress :
273+
task = progress.add_task("Préparation des rapports", total=100) # TODO: New progress bar -> step: Préparation des rapports (1 to 100%)
274+
275+
while not progress.finished :
276+
progress.update(task, description="Préparation des rapports", advance=2)
277+
time.sleep(0.2)
278+
for i in range(len(fichiers_enc)) :
279+
resultat = {
280+
'algorithme': resultats[i].algo,
281+
'fichier': resultats[i].fichier,
282+
'cle': resultats[i].cle,
283+
'tentatives': resultats[i].nb_tentatives,
284+
'temps_execution': resultats[i].temps_execution,
285+
'taux_succes': resultats[i].taux_succes,
286+
'statut_succes' : 'Succès' if resultats[i].taux_succes > 60 else 'Echec',
287+
'texte_dechiffre' : resultats[i].texte_dechiffre
288+
}
289+
rapport_mission().generer_rapport_synthese(resultat)
290+
progress.update(task, description="Mission complète effectuée.") # TODO: MAJ de la progress bar -> step: Mission complète effectuée
291+
292+
# Mise à jour des statistiques globales
293+
self.missions_completees.append({
294+
"dossier": dossier_chiffres,
295+
"resultats": resultats,
296+
"temps_total": time.time() - debut_mission
297+
})
191298

192-
# retour visuel
193-
if resultat.algo:
194-
print(f"{fichier}: {resultat.algo} (score: {resultat.score_probabilite:.2f}) \n\n")
195-
else:
196-
print(f"{fichier}: Aucun algorithme détecté")
197-
198-
# Rapport de synthèse final
199-
for i in range(6) :
200-
resultat = {
201-
'algorithme': resultats[i].algo,
202-
'fichier': resultats[i].fichier,
203-
'cle': resultats[i].cle,
204-
'tentatives': resultats[i].nb_tentatives,
205-
'temps_execution': resultats[i].temps_execution,
206-
'taux_succes': resultats[i].taux_succes,
207-
'statut_succes' : 'Succès' if resultats[i].taux_succes > 60 else 'Echec',
208-
'texte_dechiffre' : resultats[i].texte_dechiffre
209-
}
210-
rapport_mission().generer_rapport_synthese(resultat)
211-
212-
# Mise à jour des statistiques globales
213-
self.missions_completees.append({
214-
"dossier": dossier_chiffres,
215-
"resultats": resultats,
216-
"temps_total": time.time() - debut_mission
217-
})
218-
219-
return resultats
299+
return resultats
220300

221301
except Exception as e:
222302
print(f"Erreur lors de la mission complète: {str(e)}")
223303
return []
304+
224305

225306
def attaque_dictionnaire_manuelle(self, chemin_fichier: str, algorithme_choisi: str, chemin_dictionnaire: str) -> ResultatAnalyse:
226307
"""

0 commit comments

Comments
 (0)