44from rich import print
55import os
66import sys
7+ from typing import List
8+
79sys .path .append (os .path .join (os .path .dirname (__file__ ), '..' ))
810from crypto_analyzer import CryptoAnalyzer
911from utils import calculer_entropie
@@ -25,12 +27,10 @@ class ChaCha20_Analyzer(CryptoAnalyzer):
2527 _CHACHA20_LONGUEUR_BLOC: la taille du bloc de chiffrement (64 bits)
2628 """
2729
28- _CHACHA20_LONGUEUR_CLE = 32
29- _CHACHA20_LONGUEUR_NONCE = 12 #fourni
30- _CHACHA20_LONGUEUR_TAG = 16
31- _CHACHA20_LONGUEUR_BLOC = 64
32-
33-
30+ _CHACHA20_LONGUEUR_CLE : int = 32
31+ _CHACHA20_LONGUEUR_NONCE : int = 12
32+ _CHACHA20_LONGUEUR_TAG : int = 16
33+ _CHACHA20_LONGUEUR_BLOC : int = 64
3434
3535 def identifier_algo (self , chemin_fichier_chiffre : str ) -> float :
3636 """
@@ -40,142 +40,104 @@ def identifier_algo(self, chemin_fichier_chiffre: str) -> float:
4040 - vérifiant l'absence de padding (pas de contrainte de taille)
4141 - vérifiant que la taille du fichier est suffisante pour contenir un nonce
4242
43- Retourne une probabilité entre 0 et 1(Pour connaitre la probabilité que l'algo de chiffrement utilisé soit l'ChaCha20).
43+ Retourne une probabilité entre 0 et 1 (Pour connaitre la probabilité que l'algo de chiffrement utilisé soit l'ChaCha20).
4444
4545 Args:
46- chemin_fichier_chiffre(str): le chemin du fichier chiffré à traiter .
46+ chemin_fichier_chiffre(str): le chemin du fichier chiffré à traiter.
4747
4848 Returns:
49- float: La probabilité que l'algo de chiffrement utilisé soit l'ChaCha20 apres le calcul.
49+ float: La probabilité que l'algo de chiffrement utilisé soit l'ChaCha20 après le calcul.
5050 """
5151 try :
5252 with open (chemin_fichier_chiffre , 'rb' ) as f :
53- donnees = f .read ()
53+ donnees : bytes = f .read ()
5454
5555 if len (donnees ) < self ._CHACHA20_LONGUEUR_NONCE :
56- return 0.0 # Fichier trop petit pour contenir un nonce
56+ return 0.0
5757
58- # Extraire le nonce présumé (12 premiers bytes)
59- nonce = donnees [:self ._CHACHA20_LONGUEUR_NONCE ]
60- donnees_chiffrees = donnees [self ._CHACHA20_LONGUEUR_NONCE :]
58+ nonce : bytes = donnees [:self ._CHACHA20_LONGUEUR_NONCE ]
59+ donnees_chiffrees : bytes = donnees [self ._CHACHA20_LONGUEUR_NONCE :]
6160
6261 if len (donnees_chiffrees ) == 0 :
63- return 0.0 # Pas de données chiffrées
62+ return 0.0
6463
65- # Critère 1: Vérifier la taille minimale
64+ taille_min : float = 0.0
6665 if len (donnees ) >= self ._CHACHA20_LONGUEUR_NONCE + 16 :
6766 taille_min = 1.0
68- else :
69- taille_min = 0.0
7067
71- # Critère 2: Vérifier l'entropie des données chiffrées (doit être très élevée)
72- entropie = calculer_entropie (donnees_chiffrees )
73- # L'entropie d'un chiffrement ChaCha20 devrait être proche de 8 bits/octet
74- if entropie / 8.0 > 1.0 :
75- entropie_max = 1.0
76- else :
77- entropie_max = entropie / 8.0
68+ entropie : float = calculer_entropie (donnees_chiffrees )
69+ entropie_max : float = min (entropie / 8.0 , 1.0 )
7870
79- # Critère 3: Vérifier l'absence de padding (pas de contrainte de taille)
80- # ChaCha20 est un chiffrement de flux, donc pas de padding
81- # On vérifie que la taille des données chiffrées n'est pas un multiple d'une taille de bloc commune
82- taille_donnees = len (donnees_chiffrees )
71+ padding_max : float = 1.0
72+ taille_donnees : int = len (donnees_chiffrees )
8373 if taille_donnees % 16 == 0 or taille_donnees % 8 == 0 :
8474 padding_max = 0.5
85- else :
86- padding_max = 1.0
8775
88- # Critère 4: Vérifier l'entropie du nonce (doit être élevée aussi)
89- entropie_nonce = calculer_entropie (nonce )
90- if entropie_nonce / 8.0 > 1.0 :
91- nonce_max = 1.0
92- else :
93- nonce_max = entropie_nonce / 8.0
76+ entropie_nonce : float = calculer_entropie (nonce )
77+ nonce_max : float = min (entropie_nonce / 8.0 , 1.0 )
9478
95- # Calcul de la probabilité finale (moyenne pondérée des scores)
96- probabilite = (taille_min * 0.1 +
79+ probabilite : float = (taille_min * 0.1 +
9780 entropie_max * 0.4 +
9881 padding_max * 0.3 +
9982 nonce_max * 0.2 )
10083
101- return min ( probabilite , 1.0 )
84+ return probabilite
10285
10386 except Exception as e :
10487 print (f"Erreur lors de l'identification de l'algorithme: { e } " )
10588 return 0.0
10689
90+ def filtrer_dictionnaire_par_indices (self , chemin_fichier_chiffre : str ) -> List [bytes ]:
91+ # En supposant qu'elle retourne une liste de bytes pour les clés.
92+ return []
10793
108- def filtrer_dictionnaire_par_indices (self , chemin_fichier_chiffre ):
109- pass
110-
111- def generer_cles_candidates (self , chemin_fichier_chiffre ):
112-
113- '''
114- Cette fonction se charge de générer les clés candidates pour le déchiffremment du fichier chiffré en utilisant
115- la dérivation sha256 pour renforcer les clées de chiffrement.
94+ def generer_cles_candidates (self , chemin_dictionnaire : str ) -> List [bytes ]:
95+ """
96+ Cette fonction se charge de générer les clés candidates pour le déchifremment du fichier chiffré en utilisant
97+ la dérivation sha256 pour renforcer les clées de chiffrement.
11698
117-
118- Args:
119- chemin_fichier_chiffre(str) : Le chemin vers le fichier chiffré
120-
121- Returns:
122- cles_candidates (list[bytes]) : Un tableau de clés, chaque clé étant une séquence d'octets
123- '''
99+ Args:
100+ chemin_dictionnaire(str) : Le chemin vers le dictionnaire.
124101
125- donnees_fichier_filtre = self .filtrer_dictionnaire_par_indices (chemin_fichier_chiffre )
126-
127- cle_candidates : list [bytes ] = []
102+ Returns:
103+ cles_candidates (List[bytes]) : Un tableau de clés, chaque clé étant une séquence d'octets.
104+ """
105+ donnees_fichier_filtre : List [bytes ] = self .filtrer_dictionnaire_par_indices (chemin_dictionnaire )
106+ cles_candidates : List [bytes ] = []
128107 for cle in donnees_fichier_filtre :
129- cle_candidates .append (hashlib .sha256 (cle ).digest ())
130-
131- return cle_candidates
108+ cles_candidates .append (hashlib .sha256 (cle ).digest ())
109+ return cles_candidates
132110
133111 def dechiffrer (self , chemin_fichier_chiffre : str , cle_donnee : bytes ) -> bytes :
134112 if len (cle_donnee ) != 32 :
135113 raise ValueError ("Erreur : La clé n'a pas la taille correcte" )
136- else :
137- try :
138- # Utiliser le chemin complet si c'est un chemin absolu, sinon ajouter le préfixe data/
139- if os .path .isabs (chemin_fichier_chiffre ):
140- fichier_path = chemin_fichier_chiffre
141- else :
142- fichier_path = f"data/{ chemin_fichier_chiffre } "
143-
144- with open (fichier_path , 'rb' ) as f :
145- nonce = f .read (self ._CHACHA20_LONGUEUR_NONCE )
146- texte_chiffre = f .read ()
147-
148- algorithm_chacha20 = algorithms .ChaCha20 (cle_donnee , nonce )
149- cipher = Cipher (algorithm_chacha20 , mode = None )
150- decrypteur = cipher .decryptor ()
151- resultat = decrypteur .update (texte_chiffre )
152-
153- # Retourner les bytes bruts comme attendu par l'interface
154- return resultat
155-
156- except Exception as e :
157- print (f"Une erreur est survenue : { e } " )
158- return b""
159- cle_candidates .append (hashlib .sha256 (cle ).encode (encoding = "utf-8" ))
160-
161- return cle_candidates
162-
163- def dechiffrer (self ,chemin_fichier_chiffer : str ,clef :bytes )-> str :
164- if len (clef ) != 32 : return ValueError ("Erreur : La clé a pas la taille correcte " )
165- else :
166- try :
167- with open (f"data/{ chemin_fichier_chiffer } " ,'rb' ) as f :
168- nonce = f .read (16 )
169- texte_chiffrer = f .read ()
170-
171- counter = 0
172- algorithm_chacha20 = algorithms .ChaCha20 (clef ,nonce )
173- cipher = Cipher (algorithm_chacha20 ,mode = None )
174- decrypteur = cipher .decryptor ()
175- return decrypteur .update (texte_chiffrer )
176- except Exception as e :
177- print (f"Une erreur est survenu : { e } " )
178-
179-
114+
115+ try :
116+ fichier_path : str = chemin_fichier_chiffre
117+ if not os .path .isabs (chemin_fichier_chiffre ):
118+ fichier_path = f"data/{ chemin_fichier_chiffre } "
119+
120+ with open (fichier_path , 'rb' ) as f :
121+ nonce : bytes = f .read (self ._CHACHA20_LONGUEUR_NONCE )
122+ texte_chiffre : bytes = f .read ()
123+
124+ algorithm_chacha20 = algorithms .ChaCha20 (cle_donnee , nonce )
125+ cipher = Cipher (algorithm_chacha20 , mode = None )
126+ decrypteur = cipher .decryptor ()
127+ resultat : bytes = decrypteur .update (texte_chiffre )
128+
129+ return resultat
180130
181- print (ChaCha20_Analyzer ().dechiffrer ("mission2.enc" ,os .urandom (32 )))
131+ except Exception as e :
132+ print (f"Une erreur est survenue : { e } " )
133+ return b""
134+
135+ # L'appel direct a été déplacé dans un bloc if __name__ == "__main__" pour de bonnes pratiques (Mouwafic)
136+ if __name__ == "__main__" :
137+ try :
138+ resultat_dechiffrement : bytes = ChaCha20_Analyzer ().dechiffrer ("mission2.enc" , os .urandom (32 ))
139+ print (f"Résultat du déchiffrement : { resultat_dechiffrement .decode ('utf-8' )} " )
140+ except ValueError as ve :
141+ print (ve )
142+ except FileNotFoundError :
143+ print ("Erreur: Le fichier 'mission2.enc' est introuvable." )
0 commit comments