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