import tkinter as tk
from tkinter import messagebox, ttk
import sqlite3
import hashlib
from [Link] import Fernet
import os
import sys
# Augmenter la limite de récursion pour éviter les erreurs avec des processus complexes
[Link](2000)
# --- 1. CONFIGURATION CRYPTOGRAPHIQUE ---
# Clé Vigenère (Pour le Nom - EXERCICE UNIQUEMENT)
CLE_VIGENERE = "SECRETE"
# Clé Symétrique AES (Fernet) pour le Login
KEY_FILE_NAME = "[Link]"
if not [Link](KEY_FILE_NAME):
FERNET_KEY = Fernet.generate_key()
with open(KEY_FILE_NAME, "wb") as key_file:
key_file.write(FERNET_KEY)
else:
with open(KEY_FILE_NAME, "rb") as key_file:
FERNET_KEY = key_file.read()
cipher_suite = Fernet(FERNET_KEY)
# --- 2. FONCTIONS DE CHIFFREMENT & HACHAGE ---
# a. Chiffrement de Vigenère (Pour le Nom)
def chiffrer_vigenere(texte, cle):
"""Chiffre un texte en utilisant Vigenère, ne chiffre que les lettres (majuscules)."""
texte = [Link]()
cle = [Link]()
resultat = []
cle_index = 0
for char in texte:
if 'A' <= char <= 'Z':
char_pos = ord(char) - ord('A')
key_char = cle[cle_index % len(cle)]
key_pos = ord(key_char) - ord('A')
chiffre_pos = (char_pos + key_pos) % 26
[Link](chr(chiffre_pos + ord('A')))
cle_index += 1
else:
[Link](char)
return "".join(resultat)
def dechiffrer_vigenere(texte_chiffre, cle):
"""Déchiffre un texte chiffré par Vigenère."""
texte_chiffre = texte_chiffre.upper()
cle = [Link]()
resultat = []
cle_index = 0
for char in texte_chiffre:
if 'A' <= char <= 'Z':
char_pos = ord(char) - ord('A')
key_char = cle[cle_index % len(cle)]
key_pos = ord(key_char) - ord('A')
dechiffre_pos = (char_pos - key_pos + 26) % 26
[Link](chr(dechiffre_pos + ord('A')))
cle_index += 1
else:
[Link](char)
return "".join(resultat)
# b. Chiffrement AES (Fernet) pour le Login
def chiffrer_aes(texte):
"""Chiffre le texte en bytes en utilisant Fernet (AES)."""
return cipher_suite.encrypt([Link]('utf-8'))
def dechiffrer_aes(texte_chiffre_bytes):
"""Déchiffre les bytes en utilisant Fernet (AES)."""
return cipher_suite.decrypt(texte_chiffre_bytes).decode('utf-8')
# c. Hachage SHA-256 (Pour le Mot de Passe)
def hacher_password(password):
"""Hache le mot de passe en utilisant SHA-256."""
return hashlib.sha256([Link]()).hexdigest()
# --- 3. GESTION DE LA BASE DE DONNÉES SQLITE ---
DB_NAME = 'chiffrement_utilisateur_vigenere_aes_sha.db'
def configurer_db():
conn = [Link](DB_NAME)
cursor = [Link]()
[Link]('''
CREATE TABLE IF NOT EXISTS utilisateur (
iduser INTEGER PRIMARY KEY,
nom_chiffre TEXT,
login_chiffre BLOB UNIQUE, -- BLOB pour stocker les bytes AES
password_hash TEXT
)
''')
[Link]()
return conn
# --- 4. APPLICATION PRINCIPALE (AppChiffrementVigenere) ---
class AppChiffrementVigenere([Link]):
def __init__(self, master, conn, username):
super().__init__(master)
[Link]()
[Link] = conn
[Link](f"🔐 Dém. Crypto Avancée - Connecté: {username}")
# Application du thème ttk
style = [Link](self)
style.theme_use('clam')
[Link]('TFrame', background='#e0f7fa')
[Link]('TLabel', background='#e0f7fa', foreground='#004d40')
[Link]('TButton', font=('Arial', 10, 'bold'), padding=5)
[Link](padx=10, pady=10, background='#e0f7fa')
self.create_widgets()
self.afficher_db()
def create_widgets(self):
main_frame = [Link](self)
main_frame.grid(row=0, column=0, padx=10, pady=10, sticky="nsew")
# --- A. Section Enregistrement ---
[Link](main_frame, text="ENREGISTREMENT (Crypto Mixte)", font=("Arial", 12,
"bold")).grid(row=0, column=0, columnspan=2, pady=10)
[Link](main_frame, text=f"Nom (Vigenère - Clé: {CLE_VIGENERE}):").grid(row=1, column=0,
padx=5, pady=5, sticky="e")
self.entry_nom = [Link](main_frame, width=40)
self.entry_nom.grid(row=1, column=1, padx=5, pady=5, sticky="w")
[Link](main_frame, text=f"Login (AES/Fernet):").grid(row=2, column=0, padx=5, pady=5,
sticky="e")
self.entry_login = [Link](main_frame, width=40)
self.entry_login.grid(row=2, column=1, padx=5, pady=5, sticky="w")
[Link](main_frame, text="Password (SHA-256):").grid(row=3, column=0, padx=5, pady=5,
sticky="e")
self.entry_password = [Link](main_frame, width=40, show="*")
self.entry_password.grid(row=3, column=1, padx=5, pady=5, sticky="w")
[Link](main_frame, text="Chiffrer & Enregistrer", command=self.enregistrer_utilisateur,
style='TButton').grid(row=4, column=0, columnspan=2, pady=15)
# --- B. Section Affichage DB ---
[Link](main_frame, text="CONTENU DE LA BASE DE DONNÉES", font=("Arial", 10,
"bold")).grid(row=5, column=0, columnspan=2, pady=(15, 5))
self.text_output = [Link](main_frame, height=8, width=80, state=[Link], bg="#ffffff",
font=('Consolas', 9))
self.text_output.grid(row=6, column=0, columnspan=2, padx=10, pady=5)
# --- C. Section Déchiffrement ---
[Link](main_frame, text="DÉCHIFFREMENT (Nom et Login)", font=("Arial", 12,
"bold")).grid(row=7, column=0, columnspan=2, pady=(15, 5))
[Link](main_frame, text="ID de l'utilisateur à déchiffrer :").grid(row=8, column=0, padx=5,
pady=5, sticky="e")
self.entry_id_dechiffrement = [Link](main_frame, width=40)
self.entry_id_dechiffrement.grid(row=8, column=1, padx=5, pady=5, sticky="w")
[Link](main_frame, text="Déchiffrer et Afficher les Infos", command=self.dechiffrer_utilisateur,
style='TButton').grid(row=9, column=0, columnspan=2, pady=15)
self.text_dechiffre_output = [Link](main_frame, height=4, width=80, state=[Link],
bg="#fffde7", font=('Arial', 10))
self.text_dechiffre_output.grid(row=10, column=0, columnspan=2, padx=10, pady=5)
def enregistrer_utilisateur(self):
nom = self.entry_nom.get()
login = self.entry_login.get()
password = self.entry_password.get()
if not all([nom, login, password]):
[Link]("Erreur", "Tous les champs doivent être remplis.")
return
try:
# Chiffrement Vigenère pour le nom
nom_c = chiffrer_vigenere(nom, CLE_VIGENERE)
# Chiffrement AES (bytes) pour le login
login_c = chiffrer_aes(login)
# Hachage SHA-256 pour le mot de passe
password_h = hacher_password(password)
cursor = [Link]()
[Link]('''
INSERT INTO utilisateur (nom_chiffre, login_chiffre, password_hash)
VALUES (?, ?, ?)
''', (nom_c, login_c, password_h))
[Link]()
[Link]("Succès", f"Utilisateur '{[Link]()}' inséré. Nom chiffré (Vigenère):
{nom_c}")
self.afficher_db()
self.entry_nom.delete(0, [Link])
self.entry_login.delete(0, [Link])
self.entry_password.delete(0, [Link])
except [Link]:
[Link]("Erreur", "Ce login (chiffré) existe déjà. Choisissez un autre login.")
except Exception as e:
[Link]("Erreur", f"Une erreur est survenue lors de l'enregistrement : {e}")
print(e)
def afficher_db(self):
"""Affiche les données brutes de la base de données dans la zone de texte."""
self.text_output.config(state=[Link])
self.text_output.delete(1.0, [Link])
cursor = [Link]()
[Link]("SELECT iduser, nom_chiffre, login_chiffre, password_hash FROM utilisateur")
output_text = "ID | Nom (Vigenère) | Login (AES - Début des octets) | Password (SHA-256 - Début)\
n"
output_text += "-" * 85 + "\n"
for row in [Link]():
# Conversion des bytes AES en chaîne pour l'affichage (tronqué)
login_bits_display = str(row[2])[:30].replace("b'", "") + "..."
password_hash_display = row[3][:15] + "..."
# Ajustement du formatage pour le nouvel affichage
output_text += f"{row[0]:<3}| {row[1]:<14}| {login_bits_display:<30}|
{password_hash_display:<20}\n"
self.text_output.insert([Link], output_text)
self.text_output.config(state=[Link])
def dechiffrer_utilisateur(self):
self.text_dechiffre_output.config(state=[Link])
self.text_dechiffre_output.delete(1.0, [Link])
id_str = self.entry_id_dechiffrement.get()
if not id_str:
[Link]("Erreur", "Veuillez entrer l'ID de l'utilisateur à déchiffrer.")
return
try:
user_id = int(id_str)
except ValueError:
[Link]("Erreur", "L'ID doit être un nombre entier.")
return
cursor = [Link]()
[Link]("SELECT nom_chiffre, login_chiffre FROM utilisateur WHERE iduser=?", (user_id,))
row = [Link]()
if row is None:
[Link]("Erreur", f"Aucun utilisateur trouvé avec l'ID {user_id}.")
self.text_dechiffre_output.config(state=[Link])
return
nom_c, login_c_bytes = row
# 1. Déchiffrement Vigenère du Nom
nom_clair = dechiffrer_vigenere(nom_c, CLE_VIGENERE)
# 2. Déchiffrement AES du Login
try:
login_clair = dechiffrer_aes(login_c_bytes)
except Exception:
login_clair = "Erreur de déchiffrement AES (Clé Fernet invalide ou donnée corrompue)"
output_text = f"--- Informations Déchiffrées (ID: {user_id}) ---\n"
output_text += f"Nom (Clair - Vigenère) : {nom_clair}\n"
output_text += f"Login (Clair - AES/Fernet) : {login_clair}\n"
output_text += f"Password (Non réversible - SHA-256) : Non déchiffrable."
self.text_dechiffre_output.insert([Link], output_text)
self.text_dechiffre_output.config(state=[Link])
# --- 5. FENÊTRE D'ACCUEIL (LoginWindow) ---
class LoginWindow([Link]):
def __init__(self):
super().__init__()
[Link]("Authentification Crypto")
style = [Link](self)
style.theme_use('clam')
[Link]('TFrame', background='#fafafa')
[Link]('TLabel', background='#fafafa')
[Link] = configurer_db()
self.create_widgets()
def create_widgets(self):
main_frame = [Link](self, padding="15")
main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
[Link](main_frame, text="CONNEXION (AES/SHA-256)", font=("Arial", 16, "bold"),
foreground='#1565c0').grid(row=0, column=0, columnspan=2, pady=20)
[Link](main_frame, text="Login:").grid(row=1, column=0, padx=5, pady=5, sticky="e")
self.entry_login = [Link](main_frame, width=30)
self.entry_login.grid(row=1, column=1, padx=5, pady=5, sticky="w")
[Link](main_frame, text="Password:").grid(row=2, column=0, padx=5, pady=5, sticky="e")
self.entry_password = [Link](main_frame, width=30, show="*")
self.entry_password.grid(row=2, column=1, padx=5, pady=5, sticky="w")
[Link](main_frame, text="CONNEXION", command=[Link], style='TButton').grid(row=3,
column=0, pady=20, padx=5)
[Link](main_frame, text="INSCRIPTION", command=self.show_inscription,
style='TButton').grid(row=3, column=1, pady=20, padx=5)
def login(self):
login_clair = self.entry_login.get()
password_clair = self.entry_password.get()
if not login_clair or not password_clair:
[Link]("Erreur", "Veuillez entrer le login et le mot de passe.")
return
try:
# Chiffrer les entrées pour la comparaison
login_chiffre_entre = chiffrer_aes(login_clair)
password_hache_entre = hacher_password(password_clair)
cursor = [Link]()
# Cherche le login AES chiffré
[Link]("SELECT password_hash FROM utilisateur WHERE login_chiffre=?",
(login_chiffre_entre,))
row = [Link]()
if row:
password_hash_db = row[0]
# Vérifie le hash du mot de passe
if password_hache_entre == password_hash_db:
# CHANGÉ : Utilisation de 'christine' comme login par défaut pour l'affichage
username_for_display = "CHRISTINE"
[Link]("Succès", f"Connexion réussie! Bienvenue {username_for_display}")
AppChiffrementVigenere(self, [Link], username_for_display)
return
[Link]("Erreur", "Login ou mot de passe incorrect.")
except Exception as e:
[Link]("Erreur de connexion", f"Une erreur s'est produite: {e}")
print(e)
def show_inscription(self):
InscriptionWindow(self, [Link])
# --- 6. FENÊTRE D'INSCRIPTION ---
class InscriptionWindow([Link]):
def __init__(self, master, conn):
super().__init__(master)
[Link] = conn
[Link]("Création de Compte")
style = [Link](self)
style.theme_use('clam')
[Link]('TFrame', background='#e8f5e9')
[Link]('TLabel', background='#e8f5e9')
self.create_widgets()
def create_widgets(self):
main_frame = [Link](self, padding="15")
main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
[Link](main_frame, text="CRÉER UN NOUVEAU COMPTE", font=("Arial", 14, "bold"),
foreground='#2e7d32').grid(row=0, column=0, columnspan=2, pady=15)
[Link](main_frame, text="Nom:").grid(row=1, column=0, padx=5, pady=5, sticky="e")
self.entry_nom = [Link](main_frame, width=30)
self.entry_nom.grid(row=1, column=1, padx=5, pady=5, sticky="w")
[Link](main_frame, text="Login:").grid(row=2, column=0, padx=5, pady=5, sticky="e")
self.entry_login = [Link](main_frame, width=30)
self.entry_login.grid(row=2, column=1, padx=5, pady=5, sticky="w")
[Link](main_frame, text="Password:").grid(row=3, column=0, padx=5, pady=5, sticky="e")
self.entry_password = [Link](main_frame, width=30, show="*")
self.entry_password.grid(row=3, column=1, padx=5, pady=5, sticky="w")
[Link](main_frame, text="VALIDER ET ENREGISTRER", command=[Link],
style='TButton').grid(row=4, column=0, columnspan=2, pady=20)
def inscrire(self):
nom_clair = self.entry_nom.get()
login_clair = self.entry_login.get()
password_clair = self.entry_password.get()
if not all([nom_clair, login_clair, password_clair]):
[Link]("Erreur", "Tous les champs doivent être remplis.")
return
try:
# 1. Chiffrement Vigenère pour le nom
nom_c = chiffrer_vigenere(nom_clair, CLE_VIGENERE)
# 2. Chiffrement AES (bytes) pour le login
login_c = chiffrer_aes(login_clair)
# 3. Hachage SHA-256 pour le mot de passe
password_h = hacher_password(password_clair)
cursor = [Link]()
[Link]('''
INSERT INTO utilisateur (nom_chiffre, login_chiffre, password_hash)
VALUES (?, ?, ?)
''', (nom_c, login_c, password_h))
[Link]()
[Link]("Succès", "Compte créé et ENREGISTRÉ avec succès ! Vous pouvez vous
connecter.")
[Link] = [Link]
[Link]()
except [Link]:
[Link]("Erreur", "Ce login (chiffré) existe déjà. Choisissez un autre login.")
except Exception as e:
[Link]("Erreur", f"Une erreur est survenue lors de l'enregistrement : {e}")
print(e)
# --- 7. EXECUTION PRINCIPALE ---
if __name__ == "__main__":
app = LoginWindow()
[Link]()