-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathaes_gcm_analyzer.py
More file actions
134 lines (104 loc) · 5.03 KB
/
aes_gcm_analyzer.py
File metadata and controls
134 lines (104 loc) · 5.03 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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
from src.crypto_analyzer import CryptoAnalyzer
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
from src.utils import calculer_entropie
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] = []
for mot_de_passe in mots_de_passe_cible:
# Créer une nouvelle instance de PBKDF2 pour chaque mot de passe
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=self._PBKDF2_LONGUEUR_CLE,
iterations=self._PBKDF2_ITERATIONS,
salt=self._PBKDF2_SALT
)
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):
"""
Identifie si le fichier utilise l'algorithme AES GCM.
Args:
chemin_fichier_chiffre(str): Le chemin vers le fichier chiffré.
Returns:
float: Probabilité que le fichier utilise AES GCM (0.0 à 1.0).
"""
try :
with open(chemin_fichier_chiffre,'rb') as f:
if len(f.read()) < 28 : # Prise en compte de l'entropie (12 bytes) et du tag (16 bytes) comme taille minimales pour un cryptage AES-GCM
proba = 0.00
if calculer_entropie(f.read()) > 8 :
proba = 0.60
except Exception as e:
print(f"Erreur lors de l'identification de l'algorithme: {e}")
return 0.0
return proba
def dechiffrer(self, chemin_fichier_chiffre, cle_donnee):
"""
Déchiffre le fichier chiffré avec la clé donnée.
Args:
chemin_fichier_chiffre(str): Le chemin vers le fichier chiffré.
cle_donnee(bytes): La clé de déchiffrement.
Returns:
bytes: Le contenu déchiffré ou une chaîne vide en cas d'échec.
"""
try:
# Pour l'instant, retourner une chaîne vide
# TODO: Implémenter la logique de déchiffrement AES GCM
return b""
except Exception as e:
print(f"Erreur lors du déchiffrement: {e}")
return b""