Identité → Mot de passe → Hachage → Vérification → Accès → Sécurité
Mot de passe fort : Mot de passe qui résiste aux tentatives de devinette ou de piratage en raison de sa complexité.
- Identifier les caractéristiques de force
- Analyser les longueurs minimales
- Évaluer la complexité des caractères
- Tester la sécurité des mots de passe
- Au moins 12 caractères
- Majuscules et minuscules
- Chiffres et symboles
- Absence de mots du dictionnaire
- Non réutilisation
Un mot de passe doit contenir au minimum 12 caractères pour être considéré comme sûr.
Combinaison de majuscules, minuscules, chiffres et symboles rend le mot de passe plus difficile à deviner.
def est_mot_de_passe_fort(mdp):
longueur_ok = len(mdp) >= 12
majuscule_ok = any(c.isupper() for c in mdp)
minuscule_ok = any(c.islower() for c in mdp)
chiffre_ok = any(c.isdigit() for c in mdp)
special_ok = any(c in "!@#$%^&*" for c in mdp)
return all([longueur_ok, majuscule_ok, minuscule_ok, chiffre_ok, special_ok])
def evaluer_mot_de_passe(mot_de_passe):
"""Évalue la force d'un mot de passe"""
score = 0
details = []
# Longueur
if len(mot_de_passe) >= 12:
score += 2
details.append("✓ Longueur suffisante (≥12 caractères)")
elif len(mot_de_passe) >= 8:
score += 1
details.append("⚠ Longueur moyenne (8-11 caractères)")
else:
details.append("✗ Trop court (<8 caractères)")
# Majuscules
if any(c.isupper() for c in mot_de_passe):
score += 1
details.append("✓ Contient des majuscules")
else:
details.append("✗ Pas de majuscules")
# Minuscules
if any(c.islower() for c in mot_de_passe):
score += 1
details.append("✓ Contient des minuscules")
else:
details.append("✗ Pas de minuscules")
# Chiffres
if any(c.isdigit() for c in mot_de_passe):
score += 1
details.append("✓ Contient des chiffres")
else:
details.append("✗ Pas de chiffres")
# Caractères spéciaux
caracteres_speciaux = "!@#$%^&*()_+-=[]{}|;:,.<>?"
if any(c in caracteres_speciaux for c in mot_de_passe):
score += 1
details.append("✓ Contient des caractères spéciaux")
else:
details.append("✗ Pas de caractères spéciaux")
# Évaluation finale
if score >= 5:
resultat = "Très fort"
elif score >= 3:
resultat = "Fort"
elif score >= 2:
resultat = "Moyen"
else:
resultat = "Faible"
return resultat, score, details
# Exemple d'utilisation
mdp = "MotDePasse!2023"
niveau, score, details = evaluer_mot_de_passe(mdp)
print(f"Niveau: {niveau} (Score: {score}/6)")
for detail in details:
print(detail)
• Loi de la longueur : Plus le mot de passe est long, plus il est sécurisé
• Principe de la complexité : Plusieurs types de caractères augmentent la sécurité
• Synergie de la diversité : La variété des caractères rend les mots de passe plus robustes
Authentification multi-facteurs (MFA) : Méthode qui nécessite plusieurs preuves d'identité pour accéder à un compte.
- Quelque chose que vous connaissez (mot de passe)
- Quelque chose que vous avez (téléphone, token)
- Quelque chose que vous êtes (empreinte, visage)
- Emplacement géographique
- Comportement de l'utilisateur
def authentification_mot_de_passe(identifiant, mot_de_passe):
# Vérification du mot de passe
if verifie_mot_de_passe(identifiant, mot_de_passe):
return True
return False
def envoie_code_sms(numero_telephone):
import random
code = str(random.randint(100000, 999999))
# Envoie le code par SMS (simulation)
sauvegarde_code_temporaire(numero_telephone, code)
return code
def verification_mfa(identifiant, code_saisi):
code_stocke = recuperer_code_temporaire(identifiant)
if code_saisi == code_stocke:
# Nettoyer le code après utilisation
supprimer_code_temporaire(identifiant)
return True
return False
import hashlib
import time
import secrets
class SystemeAuthentification:
def __init__(self):
self.utilisateurs = {}
self.codes_temporaires = {}
def enregistrer_utilisateur(self, identifiant, mot_de_passe):
"""Enregistre un nouvel utilisateur"""
hash_mdp = hashlib.sha256(mot_de_passe.encode()).hexdigest()
self.utilisateurs[identifiant] = hash_mdp
print(f"Utilisateur {identifiant} enregistré avec succès")
def authentification_etape1(self, identifiant, mot_de_passe):
"""Première étape : authentification par mot de passe"""
if identifiant not in self.utilisateurs:
return False, "Utilisateur inconnu"
hash_saisi = hashlib.sha256(mot_de_passe.encode()).hexdigest()
if hash_saisi == self.utilisateurs[identifiant]:
# Générer un code temporaire
code = secrets.token_hex(3)[:6].upper()
self.codes_temporaires[identifiant] = {
'code': code,
'timestamp': time.time()
}
print(f"Code MFA envoyé à l'utilisateur {identifiant}")
return True, "Code MFA envoyé"
else:
return False, "Mot de passe incorrect"
def authentification_etape2(self, identifiant, code_saisi):
"""Deuxième étape : vérification du code MFA"""
if identifiant not in self.codes_temporaires:
return False, "Aucun code en attente"
info_code = self.codes_temporaires[identifiant]
# Vérifier l'expiration (5 minutes)
if time.time() - info_code['timestamp'] > 300:
del self.codes_temporaires[identifiant]
return False, "Code expiré"
if code_saisi.upper() == info_code['code']:
# Supprimer le code après utilisation
del self.codes_temporaires[identifiant]
return True, "Authentification réussie"
else:
return False, "Code incorrect"
# Exemple d'utilisation
auth = SystemeAuthentification()
auth.enregistrer_utilisateur("alice", "MotDePasse!2023")
# Étape 1
succes, message = auth.authentification_etape1("alice", "MotDePasse!2023")
print(message)
if succes:
# Étape 2 (simulée)
code_utilisateur = input("Entrez le code MFA : ")
succes2, message2 = auth.authentification_etape2("alice", code_utilisateur)
print(message2)
• Loi de la redondance : Plusieurs facteurs augmentent la sécurité
• Principe de l'isolement : Les facteurs sont indépendants
• Synergie de la sécurité : MFA rend les attaques plus difficiles
Algorithmes de hachage : Fonctions mathématiques qui transforment les données en une chaîne de longueur fixe.
- Unidirectionnel (impossible de retrouver les données)
- Résistant aux collisions
- Calcul rapide mais lent pour le brute-force
- Utilisation de sel (salt) pour renforcer la sécurité
import hashlib
def hacher_mot_de_passe(mot_de_passe):
"""Hache un mot de passe avec SHA-256"""
return hashlib.sha256(mot_de_passe.encode()).hexdigest()
import secrets
def hacher_avec_sel(mot_de_passe):
"""Hache un mot de passe avec un sel aléatoire"""
sel = secrets.token_hex(16)
mot_de_passe_avec_sel = mot_de_passe + sel
hache = hashlib.sha256(mot_de_passe_avec_sel.encode()).hexdigest()
return hache, sel
def verifier_mot_de_passe(mot_de_passe, hache_stocke, sel):
"""Vérifie un mot de passe en utilisant le sel"""
mot_de_passe_avec_sel = mot_de_passe + sel
hache_saisi = hashlib.sha256(mot_de_passe_avec_sel.encode()).hexdigest()
return hache_saisi == hache_stocke
import hashlib
import secrets
import bcrypt
class GestionHachage:
@staticmethod
def hacher_sha256(mot_de_passe, sel=None):
"""Hachage avec SHA-256"""
if sel is None:
sel = secrets.token_hex(16)
mot_de_passe_avec_sel = mot_de_passe + sel
hache = hashlib.sha256(mot_de_passe_avec_sel.encode()).hexdigest()
return hache, sel
@staticmethod
def hacher_bcrypt(mot_de_passe):
"""Hachage avec bcrypt (recommandé pour les mots de passe)"""
sel = bcrypt.gensalt()
hache = bcrypt.hashpw(mot_de_passe.encode(), sel)
return hache.decode()
@staticmethod
def verifier_bcrypt(mot_de_passe, hache_stocke):
"""Vérification avec bcrypt"""
return bcrypt.checkpw(mot_de_passe.encode(), hache_stocke.encode())
@staticmethod
def comparer_algorithmes():
"""Comparaison des algorithmes de hachage"""
mot_de_passe = "MotDePasse!2023"
# SHA-256
hache_sha, sel_sha = GestionHachage.hacher_sha256(mot_de_passe)
print(f"SHA-256: {hache_sha[:20]}...")
print(f"Sel SHA: {sel_sha}")
# Bcrypt
hache_bcrypt = GestionHachage.hacher_bcrypt(mot_de_passe)
print(f"Bcrypt: {hache_bcrypt[:20]}...")
# Vérification
verification = GestionHachage.verifier_bcrypt(mot_de_passe, hache_bcrypt)
print(f"Vérification réussie: {verification}")
# Comparaison des algorithmes
GestionHachage.comparer_algorithmes()
• Loi de l'unidirectionalité : Le hachage est irréversible
• Principe du sel : Ajouter du sel empêche les attaques par table arc-en-ciel
• Synergie de la complexité : bcrypt est préférable pour les mots de passe
Politiques de mots de passe : Ensemble de règles qui définissent la création, l'utilisation et la gestion des mots de passe.
- Complexité requise
- Expiration des mots de passe
- Historique des mots de passe
- Verrouillage des comptes
- Notifications de sécurité
class PolitiqueMotsDePasse:
def __init__(self):
self.longueur_minimale = 12
self.exiger_majuscules = True
self.exiger_chiffres = True
self.exiger_caracteres_speciaux = True
self.delai_expiration = 90 # jours
self.historique_taille = 5 # nombre de mots de passe à retenir
def valider_mot_de_passe(self, mot_de_passe):
"""Valide un mot de passe selon la politique"""
erreurs = []
if len(mot_de_passe) < self.longueur_minimale:
erreurs.append(f"Longueur insuffisante (minimum {self.longueur_minimale})")
if self.exiger_majuscules and not any(c.isupper() for c in mot_de_passe):
erreurs.append("Doit contenir au moins une majuscule")
if self.exiger_chiffres and not any(c.isdigit() for c in mot_de_passe):
erreurs.append("Doit contenir au moins un chiffre")
if self.exiger_caracteres_speciaux:
caracteres_speciaux = "!@#$%^&*()_+-=[]{}|;:,.<>?"
if not any(c in caracteres_speciaux for c in mot_de_passe):
erreurs.append("Doit contenir au moins un caractère spécial")
return len(erreurs) == 0, erreurs
def mot_de_passe_deja_utilise(self, mot_de_passe, historique):
"""Vérifie si le mot de passe a déjà été utilisé"""
hache_mdp = hashlib.sha256(mot_de_passe.encode()).hexdigest()
return hache_mdp in historique
import hashlib
import time
from datetime import datetime, timedelta
class GestionMotsDePasse:
def __init__(self):
self.utilisateurs = {} # {identifiant: {'mot_de_passe': hache, 'historique': [], 'date_modification': timestamp}}
self.politique = {
'longueur_minimale': 12,
'exiger_majuscules': True,
'exiger_chiffres': True,
'exiger_caracteres_speciaux': True,
'delai_expiration': 90, # jours
'historique_taille': 5,
'tentatives_max': 3,
'delai_verrouillage': 300 # secondes
}
def valider_mot_de_passe(self, mot_de_passe):
"""Valide un mot de passe selon la politique"""
erreurs = []
if len(mot_de_passe) < self.politique['longueur_minimale']:
erreurs.append(f"Longueur insuffisante (minimum {self.politique['longueur_minimale']} caractères)")
if self.politique['exiger_majuscules'] and not any(c.isupper() for c in mot_de_passe):
erreurs.append("Doit contenir au moins une majuscule")
if self.politique['exiger_chiffres'] and not any(c.isdigit() for c in mot_de_passe):
erreurs.append("Doit contenir au moins un chiffre")
if self.politique['exiger_caracteres_speciaux']:
caracteres_speciaux = "!@#$%^&*()_+-=[]{}|;:,.<>?"
if not any(c in caracteres_speciaux for c in mot_de_passe):
erreurs.append("Doit contenir au moins un caractère spécial")
return len(erreurs) == 0, erreurs
def changer_mot_de_passe(self, identifiant, ancien_mot_de_passe, nouveau_mot_de_passe):
"""Change le mot de passe d'un utilisateur"""
if identifiant not in self.utilisateurs:
return False, "Utilisateur inconnu"
utilisateur = self.utilisateurs[identifiant]
# Vérifier l'ancien mot de passe
ancien_hache = hashlib.sha256(ancien_mot_de_passe.encode()).hexdigest()
if ancien_hache != utilisateur['mot_de_passe']:
return False, "Ancien mot de passe incorrect"
# Valider le nouveau mot de passe
est_valide, erreurs = self.valider_mot_de_passe(nouveau_mot_de_passe)
if not est_valide:
return False, f"Mauvais format: {'; '.join(erreurs)}"
# Vérifier qu'il n'a pas déjà été utilisé
hache_nouveau = hashlib.sha256(nouveau_mot_de_passe.encode()).hexdigest()
if hache_nouveau in utilisateur['historique']:
return False, "Mot de passe déjà utilisé récemment"
# Mettre à jour
utilisateur['mot_de_passe'] = hache_nouveau
utilisateur['historique'].append(hache_nouveau)
# Garder uniquement les derniers mots de passe dans l'historique
if len(utilisateur['historique']) > self.politique['historique_taille']:
utilisateur['historique'] = utilisateur['historique'][-self.politique['historique_taille']:]
utilisateur['date_modification'] = time.time()
return True, "Mot de passe changé avec succès"
def est_expire(self, identifiant):
"""Vérifie si le mot de passe est expiré"""
if identifiant not in self.utilisateurs:
return False
utilisateur = self.utilisateurs[identifiant]
date_modification = utilisateur.get('date_modification', 0)
expiration_limite = time.time() - (self.politique['delai_expiration'] * 24 * 3600)
return date_modification < expiration_limite
# Exemple d'utilisation
gestion = GestionMotsDePasse()
gestion.utilisateurs['alice'] = {
'mot_de_passe': hashlib.sha256('AncienMotDePasse!2022'.encode()).hexdigest(),
'historique': [hashlib.sha256('AncienMotDePasse!2022'.encode()).hexdigest()],
'date_modification': time.time() - (100 * 24 * 3600) # Il y a 100 jours
}
succes, message = gestion.changer_mot_de_passe('alice', 'AncienMotDePasse!2022', 'NouveauMotDePasse!2023')
print(message)
• Loi de l'expiration : Les mots de passe doivent être changés régulièrement
• Principe de l'historique : Empêcher la réutilisation des anciens mots de passe
• Synergie de la sécurité : Plusieurs règles renforcent la protection
Attaques de mots de passe : Techniques utilisées par des attaquants pour découvrir ou contourner les mots de passe.
- Attaque par force brute
- Attaque par dictionnaire
- Attaque par table arc-en-ciel
- Phishing
- Keyloggers
class ProtectionTentatives:
def __init__(self, tentatives_max=3, delai_verrouillage=300):
self.tentatives_max = tentatives_max
self.delai_verrouillage = delai_verrouillage
self.compteur_tentatives = {}
self.heures_verrouillage = {}
def verifier_acces(self, identifiant):
"""Vérifie si l'accès est autorisé"""
if identifiant in self.heures_verrouillage:
heure_verrouillage = self.heures_verrouillage[identifiant]
if time.time() - heure_verrouillage < self.delai_verrouillage:
return False, "Compte verrouillé temporairement"
else:
# Délai écoulé, réinitialiser
del self.heures_verrouillage[identifiant]
self.compteur_tentatives[identifiant] = 0
return True, "Accès autorisé"
def incrementer_tentative(self, identifiant):
"""Incrémente le compteur de tentatives"""
if identifiant not in self.compteur_tentatives:
self.compteur_tentatives[identifiant] = 0
self.compteur_tentatives[identifiant] += 1
if self.compteur_tentatives[identifiant] >= self.tentatives_max:
self.heures_verrouillage[identifiant] = time.time()
return False, "Trop de tentatives, compte verrouillé"
return True, f"Tentative {self.compteur_tentatives[identifiant]}/{self.tentatives_max}"
class SystemeProtection:
def __init__(self):
self.protection = ProtectionTentatives()
self.utilisateurs = {} # Simule la base d'utilisateurs
def authentifier(self, identifiant, mot_de_passe):
"""Système d'authentification avec protection"""
# Vérifier le verrouillage
acces_autorise, message = self.protection.verifier_acces(identifiant)
if not acces_autorise:
return False, message
# Simuler la vérification du mot de passe
if self.utilisateurs.get(identifiant) == hashlib.sha256(mot_de_passe.encode()).hexdigest():
# Réinitialiser le compteur en cas de succès
self.protection.compteur_tentatives[identifiant] = 0
return True, "Authentification réussie"
else:
# Incrémenter les tentatives échouées
_, message = self.protection.incrementer_tentative(identifiant)
return False, message
import time
import hashlib
import threading
import queue
class SystemeProtectionAvance:
def __init__(self):
self.utilisateurs = {}
self.compteur_tentatives = {}
self.heures_verrouillage = {}
self.adresses_ip = {} # Pour limiter par IP
self.tentatives_max = 3
self.delai_verrouillage = 300 # 5 minutes
self.tentatives_max_ip = 10 # par heure
self.delai_ip = 3600 # 1 heure
self.file_attente = queue.Queue()
self.lock = threading.Lock()
def ajouter_utilisateur(self, identifiant, mot_de_passe):
"""Ajoute un utilisateur avec son mot de passe haché"""
self.utilisateurs[identifiant] = hashlib.sha256(mot_de_passe.encode()).hexdigest()
def est_verrouille_ip(self, adresse_ip):
"""Vérifie si l'adresse IP est verrouillée"""
with self.lock:
if adresse_ip not in self.adresses_ip:
return False
ip_info = self.adresses_ip[adresse_ip]
if time.time() - ip_info['heure_derniere'] < self.delai_ip:
return ip_info['tentatives'] >= self.tentatives_max_ip
else:
# Réinitialiser le compteur après le délai
del self.adresses_ip[adresse_ip]
return False
def est_verrouille_utilisateur(self, identifiant):
"""Vérifie si l'utilisateur est verrouillé"""
with self.lock:
if identifiant in self.heures_verrouillage:
heure_verrouillage = self.heures_verrouillage[identifiant]
if time.time() - heure_verrouillage < self.delai_verrouillage:
return True
else:
# Délai écoulé, réinitialiser
del self.heures_verrouillage[identifiant]
self.compteur_tentatives[identifiant] = 0
return False
return False
def authentifier(self, identifiant, mot_de_passe, adresse_ip):
"""Système d'authentification avec protection avancée"""
# Vérifier l'IP
if self.est_verrouille_ip(adresse_ip):
return False, "Adresse IP bloquée pour tentatives excessives"
# Vérifier le verrouillage de l'utilisateur
if self.est_verrouille_utilisateur(identifiant):
return False, "Compte verrouillé temporairement"
# Vérifier si le mot de passe est correct
hache_saisi = hashlib.sha256(mot_de_passe.encode()).hexdigest()
if identifiant in self.utilisateurs and self.utilisateurs[identifiant] == hache_saisi:
# Réinitialiser les tentatives en cas de succès
with self.lock:
if identifiant in self.compteur_tentatives:
del self.compteur_tentatives[identifiant]
if adresse_ip in self.adresses_ip:
del self.adresses_ip[adresse_ip]
return True, "Authentification réussie"
else:
# Gérer les tentatives échouées
with self.lock:
# Compter la tentative pour l'utilisateur
if identifiant not in self.compteur_tentatives:
self.compteur_tentatives[identifiant] = 0
self.compteur_tentatives[identifiant] += 1
# Compter la tentative pour l'IP
if adresse_ip not in self.adresses_ip:
self.adresses_ip[adresse_ip] = {'tentatives': 0, 'heure_derniere': time.time()}
self.adresses_ip[adresse_ip]['tentatives'] += 1
self.adresses_ip[adresse_ip]['heure_derniere'] = time.time()
if self.compteur_tentatives[identifiant] >= self.tentatives_max:
self.heures_verrouillage[identifiant] = time.time()
return False, f"Trop de tentatives, compte verrouillé pour {self.delai_verrouillage//60} minutes"
tentatives_restantes = self.tentatives_max - self.compteur_tentatives[identifiant]
return False, f"Mauvais mot de passe, {tentatives_restantes} tentatives restantes"
# Exemple d'utilisation
systeme = SystemeProtectionAvance()
systeme.ajouter_utilisateur("alice", "MotDePasse!2023")
# Test d'authentification
resultat, message = systeme.authentifier("alice", "MauvaisMotDePasse", "192.168.1.1")
print(message)
• Loi de la limitation : Restreindre le nombre de tentatives
• Principe de la temporisation : Verrouiller temporairement les comptes
• Synergie de la surveillance : Suivre les tentatives par IP et par utilisateur
- Hachage sécurisé : Utiliser bcrypt, scrypt ou Argon2
- Utilisation de sel : Ajouter un sel unique à chaque mot de passe
- Limitation des tentatives : Verrouiller les comptes après plusieurs échecs
- Authentification multi-facteurs : Exiger plusieurs preuves d'identité
- Politiques de mot de passe : Règles de complexité et d'expiration
- Un mot de passe fort contient au moins 12 caractères avec divers types
- L'authentification multi-facteurs renforce considérablement la sécurité
- Le hachage avec sel empêche les attaques par tables arc-en-ciel
- Les politiques de mots de passe doivent être strictes mais raisonnables
- La protection contre les attaques doit être proactive
Création → Hachage → Stockage → Validation → Authentification → Protection