Skip to content

Commit ac4d295

Browse files
Eunock-webe-mandywesley-kamimouwaficbdr
authored
Implementation de la fonction identifier algo (#25)
* Intégration de AesCbcAnalyzer dans DetecteurCryptoOrchestrateur. * Debut de l'implementation du code dans la classe principale avec le menu * Documentation de la fonction d'entropie * Suite de l'implementation du code dans la classe principale avec le menu * Essai de fusion (1/2) * 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) * Update de l'option quitter * 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. * Revu des fonctions pour une meilleure optimisation * Ajout du guide d'utilisation * Unsaved files * Mise en place de la fonction de génération de clés candidates * prémices du déchiffrement Chacha20 * logique ddecryptage * Correction des erreurs dans la fonction identifier_algo --------- Co-authored-by: e-mandy <andymfrd02@gmail.com> Co-authored-by: wesley-kami <okwuwesley@gmail.com> Co-authored-by: mouwaficbdr <badaroumouwafic@gmail.com>
1 parent 77177f8 commit ac4d295

1 file changed

Lines changed: 134 additions & 4 deletions

File tree

src/analyzers/chacha20_analyzer.py

Lines changed: 134 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,116 @@
1+
# Import des modules
12
import hashlib
23
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
34
from rich import print
45
import os, struct
6+
import math
7+
import sys
8+
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
9+
from crypto_analyzer import CryptoAnalyzer
10+
from utils import calculer_entropie
11+
12+
# Définition de la classe ChaCha20_Analyzer
13+
class ChaCha20_Analyzer(CryptoAnalyzer):
14+
"""
15+
Détermine si l'algo ChaCha20 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.
16+
17+
Cette classe a trois méthodes:
18+
- identifier_algo: Détermine si l'algo de chiffrement utilisé sur le fichier chiffré qui lui est passé en paramètre est l'ChaCha20.
19+
- generer_cles_candidates: Génère une liste de clés candidates pour le déchiffrement du fichier chiffré
20+
- dechiffrer: fait le déchiffrement proprement dit sur la base de la liste des clés générées
21+
22+
Attributes:
23+
_CHACHA20_LONGUEUR_CLE: la taille de la clé de chiffrement (32 octets)
24+
_CHACHA20_LONGUEUR_NONCE: la taille du vecteur d'initialisation (12 octets)
25+
_CHACHA20_LONGUEUR_TAG: la taille de l'empreinte de chiffrement (16 octets)
26+
_CHACHA20_LONGUEUR_BLOC: la taille du bloc de chiffrement (64 bits)
27+
"""
28+
29+
_CHACHA20_LONGUEUR_CLE = 32
30+
_CHACHA20_LONGUEUR_NONCE = 12 #fourni
31+
_CHACHA20_LONGUEUR_TAG = 16
32+
_CHACHA20_LONGUEUR_BLOC = 64
33+
34+
35+
36+
def identifier_algo(self, chemin_fichier_chiffre: str) -> float:
37+
"""
38+
Détermine la probabilité que l'algo de chiffrement utilisé soit l'ChaCha20 en:
39+
- vérifiant la présence d'un nonce de 12 bytes en début de fichier
40+
- vérifiant l'entropie très élevée sur l'ensemble des données
41+
- vérifiant l'absence de padding (pas de contrainte de taille)
42+
- vérifiant que la taille du fichier est suffisante pour contenir un nonce
43+
44+
Retourne une probabilité entre 0 et 1(Pour connaitre la probabilité que l'algo de chiffrement utilisé soit l'ChaCha20).
45+
46+
Args:
47+
chemin_fichier_chiffre(str): le chemin du fichier chiffré à traiter .
48+
49+
Returns:
50+
float: La probabilité que l'algo de chiffrement utilisé soit l'ChaCha20 apres le calcul.
51+
"""
52+
try:
53+
with open(chemin_fichier_chiffre, 'rb') as f:
54+
donnees = f.read()
55+
56+
if len(donnees) < self._CHACHA20_LONGUEUR_NONCE:
57+
return 0.0 # Fichier trop petit pour contenir un nonce
58+
59+
# Extraire le nonce présumé (12 premiers bytes)
60+
nonce = donnees[:self._CHACHA20_LONGUEUR_NONCE]
61+
donnees_chiffrees = donnees[self._CHACHA20_LONGUEUR_NONCE:]
62+
63+
if len(donnees_chiffrees) == 0:
64+
return 0.0 # Pas de données chiffrées
65+
66+
# Critère 1: Vérifier la taille minimale
67+
if len(donnees) >= self._CHACHA20_LONGUEUR_NONCE + 16:
68+
taille_min = 1.0
69+
else:
70+
taille_min = 0.0
71+
72+
# Critère 2: Vérifier l'entropie des données chiffrées (doit être très élevée)
73+
entropie = calculer_entropie(donnees_chiffrees)
74+
# L'entropie d'un chiffrement ChaCha20 devrait être proche de 8 bits/octet
75+
if entropie / 8.0 > 1.0:
76+
entropie_max = 1.0
77+
else:
78+
entropie_max = entropie / 8.0
79+
80+
# Critère 3: Vérifier l'absence de padding (pas de contrainte de taille)
81+
# ChaCha20 est un chiffrement de flux, donc pas de padding
82+
# On vérifie que la taille des données chiffrées n'est pas un multiple d'une taille de bloc commune
83+
taille_donnees = len(donnees_chiffrees)
84+
if taille_donnees % 16 == 0 or taille_donnees % 8 == 0:
85+
padding_max = 0.5
86+
else:
87+
padding_max = 1.0
88+
89+
# Critère 4: Vérifier l'entropie du nonce (doit être élevée aussi)
90+
entropie_nonce = calculer_entropie(nonce)
91+
if entropie_nonce / 8.0 > 1.0:
92+
nonce_max = 1.0
93+
else:
94+
nonce_max = entropie_nonce / 8.0
95+
96+
# Calcul de la probabilité finale (moyenne pondérée des scores)
97+
probabilite = (taille_min * 0.1 +
98+
entropie_max * 0.4 +
99+
padding_max * 0.3 +
100+
nonce_max * 0.2)
101+
102+
return min(probabilite, 1.0)
103+
104+
except Exception as e:
105+
print(f"Erreur lors de l'identification de l'algorithme: {e}")
106+
return 0.0
5107

6-
class ChaCha20_Analyzer:
7108

8109
def filtrer_dictionnaire_par_indices(self, chemin_fichier_chiffre):
9110
pass
10111

112+
def generer_cles_candidates(self, chemin_fichier_chiffre):
11113

12-
13-
def generer_cle_candidates(self, chemin_fichier_chiffre):
14114
'''
15115
Cette fonction se charge de générer les clés candidates pour le déchiffremment du fichier chiffré en utilisant
16116
la dérivation sha256 pour renforcer les clées de chiffrement.
@@ -21,13 +121,42 @@ def generer_cle_candidates(self, chemin_fichier_chiffre):
21121
22122
Returns:
23123
cles_candidates (list[bytes]) : Un tableau de clés, chaque clé étant une séquence d'octets
24-
25124
'''
26125

27126
donnees_fichier_filtre = self.filtrer_dictionnaire_par_indices(chemin_fichier_chiffre)
28127

29128
cle_candidates: list[bytes] = []
30129
for cle in donnees_fichier_filtre:
130+
cle_candidates.append(hashlib.sha256(cle).digest())
131+
132+
return cle_candidates
133+
134+
def dechiffrer(self, chemin_fichier_chiffre: str, cle_donnee: bytes) -> bytes:
135+
if len(cle_donnee) != 32:
136+
raise ValueError("Erreur : La clé n'a pas la taille correcte")
137+
else:
138+
try:
139+
# Utiliser le chemin complet si c'est un chemin absolu, sinon ajouter le préfixe data/
140+
if os.path.isabs(chemin_fichier_chiffre):
141+
fichier_path = chemin_fichier_chiffre
142+
else:
143+
fichier_path = f"data/{chemin_fichier_chiffre}"
144+
145+
with open(fichier_path, 'rb') as f:
146+
nonce = f.read(self._CHACHA20_LONGUEUR_NONCE)
147+
texte_chiffre = f.read()
148+
149+
algorithm_chacha20 = algorithms.ChaCha20(cle_donnee, nonce)
150+
cipher = Cipher(algorithm_chacha20, mode=None)
151+
decrypteur = cipher.decryptor()
152+
resultat = decrypteur.update(texte_chiffre)
153+
154+
# Retourner les bytes bruts comme attendu par l'interface
155+
return resultat
156+
157+
except Exception as e:
158+
print(f"Une erreur est survenue : {e}")
159+
return b""
31160
cle_candidates.append(hashlib.sha256(cle).encode(encoding="utf-8"))
32161

33162
return cle_candidates
@@ -52,4 +181,5 @@ def dechiffrer(self,chemin_fichier_chiffer : str ,clef :bytes)->str:
52181
print(f"Une erreur est survenu : {e}")
53182

54183

184+
55185
# print(ChaCha20_Analyzer().dechiffrer("mission2.enc",os.urandom(32)))

0 commit comments

Comments
 (0)