ToolPal
Un cadenas posé sur un clavier d'ordinateur portable, symbolisant la sécurité numérique et la protection des mots de passe.

Hachage de mots de passe avec Bcrypt : pourquoi c'est important et comment l'utiliser

📷 Pixabay / Pexels

Hachage de mots de passe avec Bcrypt : pourquoi c'est important et comment l'utiliser

Les mots de passe stockés sous forme de hachages SHA-256 peuvent être craqués en quelques minutes. Bcrypt est conçu pour être lent -- et c'est précisément le but. Découvrez comment bcrypt fonctionne, comment choisir un facteur de coût, et comment l'implémenter en Node.js, Python et PHP.

7 avril 20269 min de lecture

Le problème du stockage des mots de passe

Imaginez que vous construisez un système de connexion. Un utilisateur crée un compte avec le mot de passe hunter2. Vous devez stocker quelque chose dans votre base de données pour que, lorsqu'il se connecte la semaine prochaine, vous puissiez vérifier qu'il a entré la bonne valeur.

La solution naïve est de stocker hunter2 directement. C'est catastrophique. Toute violation de base de données, toute injection SQL, tout backup laissé dans un bucket S3 mal configuré -- l'attaquant dispose maintenant du mot de passe réel de chaque utilisateur.

L'étape suivante est de le hacher. SHA-256("hunter2") vous donne une chaîne de longueur fixe que vous ne pouvez pas inverser. Stockez cela à la place. Mieux, non ?

Mieux -- mais pas suffisant.

Le problème est que SHA-256 est conçu pour être rapide. Les GPU modernes peuvent calculer des milliards de hachages SHA-256 par seconde. Un attaquant disposant d'une base de données de mots de passe hachés en SHA-256 et d'un bon GPU peut craquer une part significative des mots de passe courants en heures, parfois en minutes, en utilisant des tables précalculées (rainbow tables) ou des attaques par dictionnaire.

Bcrypt a été spécifiquement conçu pour résoudre ce problème. Il est intentionnellement lent, et la vitesse est configurable.

Vous pouvez expérimenter directement avec les hachages bcrypt grâce à notre Bcrypt Hash Generator -- aucune configuration requise.

Ce qu'est réellement Bcrypt

Bcrypt est une fonction de hachage de mots de passe conçue par Niels Provos et David Mazieres en 1999, basée sur le chiffrement Blowfish. Contrairement à SHA-256 ou MD5 (fonctions de hachage cryptographiques générales), bcrypt a été construit dès le départ spécifiquement pour le stockage des mots de passe.

Trois propriétés le rendent bien adapté :

1. Il est lent par conception

Bcrypt inclut un facteur de coût configurable (également appelé facteur de travail ou tours de sel). La fonction effectue 2^coût itérations en interne. Augmenter le facteur de coût de 1 double le temps de calcul. Cela signifie que vous pouvez ajuster la vitesse pour correspondre à votre matériel -- et à mesure que le matériel devient plus rapide, vous pouvez augmenter le facteur de coût pour rester en avance.

Un hachage SHA-256 prend des microsecondes. Un hachage bcrypt avec le coût 12 prend environ 200 à 300 millisecondes. Cette différence semble petite, mais elle change radicalement l'économie de l'attaquant.

2. Il gère automatiquement le salage

Un sel est une valeur aléatoire ajoutée au mot de passe avant le hachage. Le salage garantit que deux utilisateurs avec le même mot de passe obtiennent des hachages différents, et il empêche les attaques par rainbow tables précalculées.

Bcrypt génère automatiquement un sel aléatoire cryptographique de 128 bits et l'intègre dans le hachage de sortie. Vous n'avez pas besoin de gérer les sels vous-même.

3. Le hachage est autonome

La sortie de bcrypt contient la version de l'algorithme, le facteur de coût, le sel et le hachage -- le tout en une seule chaîne. Cela signifie que vous n'avez besoin de stocker qu'une seule chaîne par utilisateur, et vous pouvez vérifier un mot de passe sans récupérer le sel séparément.

Un hachage bcrypt typique ressemble à ceci :

$2b$12$LJ3m6gEwO/fSFqCVXWLwOeR/dYtTVkRDCwoGLBE0Fg6voFEOB5viy

Décomposition :

$2b$     -- version de l'algorithme (2b est la norme actuelle)
12$      -- facteur de coût (2^12 = 4 096 itérations du calendrier de clés)
LJ3m6gEwO/fSFqCVXWLwOe  -- sel encodé en base64 sur 22 caractères (128 bits)
R/dYtTVkRDCwoGLBE0Fg6voFEOB5viy  -- hachage encodé en base64 sur 31 caractères

Hachage vs. Chiffrement : La distinction clé

Cette distinction mérite d'être énoncée clairement.

Le hachage est une fonction unidirectionnelle. Vous entrez un mot de passe et obtenez un hachage. Il n'y a pas de clé, pas d'opération inverse. La seule façon de vérifier si un mot de passe correspond à un hachage est de hacher le mot de passe candidat et de comparer le résultat.

Le chiffrement est une fonction bidirectionnelle. Vous chiffrez des données avec une clé et pouvez les déchiffrer en original avec la même (ou une clé associée).

Les mots de passe doivent toujours être hachés, pas chiffrés. Si vous chiffrez les mots de passe, votre système contient quelque part une clé de déchiffrement, et quiconque obtient cette clé a tous les mots de passe de vos utilisateurs. Avec le hachage, une violation de base de données expose des hachages, pas des mots de passe -- et avec bcrypt, ces hachages sont longs à craquer.

Le facteur de coût : Choisir la bonne lenteur

Le facteur de coût contrôle directement le calcul effectué par bcrypt. Chaque incrément double le travail.

Facteur de coûtItérationsTemps approximatif (serveur typique)
101 024~65ms
112 048~130ms
124 096~250ms
138 192~500ms
1416 384~1 000ms

Les temps ci-dessus varient considérablement selon le matériel. Effectuez des benchmarks sur votre matériel de production réel avant de décider.

La recommandation actuelle de l'OWASP est un facteur de coût de 10 au minimum, ciblant un temps de hachage de 100 ms ou plus. La plupart des praticiens utilisent 12 comme valeur par défaut raisonnable aujourd'hui.

Le compromis :

  • Trop bas (8 ou moins) : Les hachages sont assez rapides pour qu'un attaquant disposant d'un bon GPU puisse progresser rapidement contre une base de données compromise.
  • Trop haut (15+) : Les demandes de connexion légitimes prennent plus d'une seconde chacune, ce qui est perceptible pour les utilisateurs et crée un potentiel de déni de service.
  • Zone idéale (~12) : ~250 ms par hachage est assez lent pour entraver significativement les attaquants, assez rapide pour que les utilisateurs ne le remarquent pas.

Implémenter Bcrypt : Exemples de code

Node.js

import bcrypt from 'bcrypt';

const COST_FACTOR = 12;

// Hachage d'un mot de passe
async function hashPassword(plaintext) {
  const hash = await bcrypt.hash(plaintext, COST_FACTOR);
  return hash;
  // "$2b$12$..." -- stocker cette chaîne dans votre base de données
}

// Vérification d'un mot de passe lors de la connexion
async function verifyPassword(plaintext, storedHash) {
  const match = await bcrypt.compare(plaintext, storedHash);
  return match; // true ou false
}

// Exemple d'utilisation
const hash = await hashPassword('hunter2');
console.log(hash); // $2b$12$...

const valid = await verifyPassword('hunter2', hash);
console.log(valid); // true

const invalid = await verifyPassword('wrongpassword', hash);
console.log(invalid); // false

Python (avec le paquet bcrypt)

import bcrypt

COST_FACTOR = 12

def hash_password(plaintext: str) -> str:
    """Hache un mot de passe et retourne la chaîne de hachage bcrypt."""
    password_bytes = plaintext.encode('utf-8')
    salt = bcrypt.gensalt(rounds=COST_FACTOR)
    hashed = bcrypt.hashpw(password_bytes, salt)
    return hashed.decode('utf-8')

def verify_password(plaintext: str, stored_hash: str) -> bool:
    """Vérifie un mot de passe en clair contre un hachage bcrypt stocké."""
    password_bytes = plaintext.encode('utf-8')
    hash_bytes = stored_hash.encode('utf-8')
    return bcrypt.checkpw(password_bytes, hash_bytes)

# Utilisation
hash_value = hash_password('hunter2')
print(hash_value)  # $2b$12$...

print(verify_password('hunter2', hash_value))       # True
print(verify_password('wrongpassword', hash_value)) # False

PHP

<?php

// Hachage d'un mot de passe
function hashPassword(string $plaintext): string {
    return password_hash($plaintext, PASSWORD_BCRYPT, ['cost' => 12]);
}

// Vérification d'un mot de passe
function verifyPassword(string $plaintext, string $storedHash): bool {
    return password_verify($plaintext, $storedHash);
}

// Utilisation
$hash = hashPassword('hunter2');
echo $hash; // $2y$12$...

var_dump(verifyPassword('hunter2', $hash));       // bool(true)
var_dump(verifyPassword('wrongpassword', $hash)); // bool(false)
?>

Erreurs courantes et comment les éviter

Stocker des mots de passe en clair ou avec un encodage réversible

Base64 est un encodage, pas un hachage. base64("hunter2") donne aHVudGVyMg==. Tout attaquant voyant cela peut le décoder en une ligne.

Utiliser des fonctions de hachage rapides pour les mots de passe

SHA-256, SHA-512, MD5, SHA-1 -- tous sont conçus pour être rapides. La rapidité est la mauvaise propriété pour le hachage de mots de passe.

Le problème de troncature à 72 octets

La spécification bcrypt originale ne traite que les 72 premiers octets de l'entrée. La solution standard est de hacher d'abord l'entrée avec SHA-256, puis de hacher ce résultat avec bcrypt :

import crypto from 'crypto';
import bcrypt from 'bcrypt';

async function hashLongPassword(plaintext) {
  const prehashed = crypto
    .createHash('sha256')
    .update(plaintext)
    .digest('base64');

  return bcrypt.hash(prehashed, 12);
}

Tester les hachages Bcrypt

Notre Bcrypt Hash Generator est utile pour :

  • Générer des hachages de test pendant le développement sans configurer un projet
  • Vérifier que votre implémentation produit une sortie bcrypt valide
  • Tester rapidement la vérification hachage-mot de passe dans votre code

L'outil fonctionne entièrement dans votre navigateur et n'envoie jamais de données à un serveur.

Bcrypt vs. les alternatives

AlgorithmeIntensif en mémoireRésistant au GPUStatut OWASPNotes
BcryptNonPartielRecommandéÉprouvé, limite 72 octets
Argon2idOuiOuiPréféréVainqueur PHC, plus récent
scryptOuiOuiAcceptableIntensif en mémoire, paramètres complexes
PBKDF2NonNonAcceptableApprouvé NIST, conforme FIPS
SHA-256 (simple)NonNonNe pas utiliserPas un hachage de mot de passe

Conclusion

Le hachage des mots de passe est l'un de ces domaines où la différence entre "fonctionne" et "fonctionne correctement" compte beaucoup. Bcrypt vous offre trois choses importantes : une lenteur intentionnelle, un salage automatique et un format de sortie autonome. Ce n'est pas la dernière option, mais elle est bien testée, universellement prise en charge et correcte.

Utilisez le facteur de coût 12 comme point de départ. Faites des benchmarks sur votre matériel réel. Augmentez-le si votre serveur peut hacher confortablement en moins de 200 ms. Et si vous partez de zéro, jetez un coup d'oeil à Argon2id.

Outils et ressources associés

Questions Fréquentes

Partager

XLinkedIn

Articles associés