Skip to content

Commit ffcf4de

Browse files
authored
add: Implémentation de Aes_gcm_analyzer.generer_cles_candidates (#35)
1 parent 4472e76 commit ffcf4de

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed

src/analyzers/aes_gcm_analyzer.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
from ..crypto_analyzer import CryptoAnalyzer
2+
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
3+
from cryptography.hazmat.primitives import hashes
4+
import re
5+
6+
class Aes_Gcm_Analyzer(CryptoAnalyzer):
7+
'''Détermine si l'algo aes_gcm 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.
8+
9+
Cette classe a trois méthodes principales:
10+
- identifier_algo: Détermine si l'algo de chiffrement utilsé sur le fichier chiffré qui lui est passé en paramètre est l'aes_gcm.
11+
- generer_cles_candidates: Génère une liste de clés candidates pour le déchiffrement du fichier chiffré
12+
- dechiffrer: fait le déchiffrement proprement dit sur la base de la liste des clés générées
13+
14+
Attributes:
15+
_PBKDF2_SALT: le salt utilisé pour le chiffrement
16+
_PBKDF2_ITERATIONS: le nombre d'itérations faites au chiffrement
17+
_PBKDF2_LONGUEUR_CLE: la longueur en octets de la clé à utiliser
18+
19+
'''
20+
21+
_PBKDF2_SALT = b"AES_GCM_SALT_2024" #Fourni
22+
_PBKDF2_ITERATIONS = 10000 #Fourni
23+
_PBKDF2_LONGUEUR_CLE = 32 #Longueur de la clé
24+
25+
def __filtrer_dictionnaire_par_indice(self, chemin_dictionnaire: str) -> list[str]:
26+
"""
27+
Filtre le dictionnaire en se basant sur les indices de la mission 4.
28+
L'indice pointe vers le format de clé "Acronyme en majuscules + 4 chiffres".
29+
30+
Args:
31+
chemin_dictionnaire(str): Le chemin vers le fichier de dictionnaire.
32+
33+
Returns:
34+
list[str]: Une liste de mots de passe filtrés.
35+
"""
36+
mots_filtres: list[str] = []
37+
38+
# L'année courante
39+
annee_courante = "2024" #Normalement 2025 mais on considère 2024 pour se conformer à la wordlist
40+
41+
# Définition du motif d'acronyme de 4 lettres en majuscules
42+
# On utilise une expression régulière pour plus de robustesse
43+
motif_acronyme = re.compile(r"^[A-Z]{4}$")
44+
45+
try:
46+
with open(chemin_dictionnaire, "r", encoding="utf-8") as f:
47+
for ligne in f:
48+
mot = ligne.strip()
49+
50+
# Vérifie si le mot de passe correspond au format de l'indice
51+
# ex: NATO2024, UN2024, etc.
52+
if mot.endswith(annee_courante):
53+
acronyme = mot[:-4] # Extrait la partie acronyme
54+
if motif_acronyme.match(acronyme):
55+
mots_filtres.append(mot)
56+
57+
except FileNotFoundError:
58+
print(f"Erreur : Le fichier de dictionnaire '{chemin_dictionnaire}' est introuvable.")
59+
return []
60+
61+
return mots_filtres
62+
63+
def generer_cles_candidates(self, chemin_dictionnaire: str) -> list[bytes]:
64+
'''
65+
Génère les clées candidates pour déchiffrer le fichier à partir de la liste retournée par filtrer_dictionnaire_par_indices.
66+
67+
Args:
68+
chemin_dictionnaire(str): le chemin du dictionnaire de mots de passes pour l'attaque par dictionnaire.
69+
70+
Returns:
71+
list[bytes]: liste des clés candidates.
72+
'''
73+
74+
mots_de_passe_cible = self.__filtrer_dictionnaire_par_indice(chemin_dictionnaire)
75+
76+
clees_candidates: list[bytes] = []
77+
kdf = PBKDF2HMAC(
78+
algorithm=hashes.SHA256(),
79+
length=self._PBKDF2_LONGUEUR_CLE,
80+
iterations=self._PBKDF2_ITERATIONS,
81+
salt=self._PBKDF2_SALT
82+
)
83+
for mot_de_passe in mots_de_passe_cible:
84+
mot_de_passe_en_octets: bytes = mot_de_passe.encode('utf-8')
85+
cle_derivee: bytes = kdf.derive(mot_de_passe_en_octets)
86+
clees_candidates.append(cle_derivee)
87+
88+
return clees_candidates

0 commit comments

Comments
 (0)