Bcrypt pour JavaScript (Node.js) : guide complet
1. Qu'est-ce que Bcrypt et pourquoi l'utiliser
Bcrypt est une fonction de hachage cryptographique adaptative, spécialement conçue pour le stockage sécurisé des mots de passe. Contrairement aux fonctions de hachage classiques (MD5, SHA-1, SHA-256) qui sont optimisées pour la rapidité, Bcrypt est volontairement lent et gourmand en ressources. Cela rend les attaques par force brute et les tables arc-en-ciel quasiment impossibles. La bibliothèque bcrypt pour Node.js offre une interface simple et fiable pour hacher et vérifier les mots de passe.
Pourquoi utiliser Bcrypt ? Lors de l'inscription d'un utilisateur sur un site, son mot de passe ne doit jamais être stocké en clair. Si la base de données est compromise, un attaquant aurait accès à tous les mots de passe. Bcrypt résout ce problème : vous hachez le mot de passe avec un « sel » (salt) unique et ne conservez que le hachage. Lors de la connexion, vous hachez à nouveau le mot de passe saisi et le comparez au hachage stocké. Bcrypt génère et intègre automatiquement le sel dans le résultat, vous n'avez donc pas besoin de le stocker séparément.
La caractéristique clé de Bcrypt est la possibilité de régler le « facteur de coût » (cost factor). Plus la valeur de cost est élevée, plus le calcul du hachage prend du temps. Avec l'augmentation de la puissance de calcul, il suffit d'augmenter le cost, et les anciens hachages restent valides (la vérification utilise le cost stocké dans le hachage). Cela rend Bcrypt résistant aux progrès futurs en matière d'accélération matérielle.
2. Installation
Pour installer la bibliothèque Bcrypt dans un projet Node.js, exécutez la commande suivante dans le terminal (à la racine du projet) :
npm install bcrypt
Après l'installation, vous pouvez importer la bibliothèque dans votre code :
const bcrypt = require('bcrypt');
Si vous utilisez les modules ES (type: "module" dans package.json), l'importation se fera ainsi :
import bcrypt from 'bcrypt';
3. Démarrage rapide — exemple minimal fonctionnel
Dans cet exemple, nous hachons un mot de passe, puis nous le vérifions. C'est la base de tout système d'authentification.
const bcrypt = require('bcrypt');
const plainPassword = 'mySuperSecretPassword123!';
const saltRounds = 10;
// Hachage du mot de passe
bcrypt.hash(plainPassword, saltRounds, function(err, hash) {
if (err) {
console.error('Erreur de hachage :', err);
return;
}
console.log('Hachage du mot de passe :', hash);
// Vérification du mot de passe
bcrypt.compare(plainPassword, hash, function(err, result) {
if (err) {
console.error('Erreur de comparaison :', err);
return;
}
console.log('Mot de passe correct :', result); // true
});
});
Ce code fait deux choses : il crée un hachage du mot de passe, puis vérifie si le mot de passe d'origine correspond à ce hachage. Notez que saltRounds détermine la complexité des calculs (valeur recommandée : 10–12).
4. Méthodes/fonctions/classes principales
4.1. bcrypt.hash(data, saltOrRounds, callback)
Signature : bcrypt.hash(data: string | Buffer, saltOrRounds: number | string, callback: (err: Error | null, encrypted: string) => void): void
Fonction : Hache de manière asynchrone une chaîne ou un Buffer. saltOrRounds peut être un nombre (nombre de rounds) ou un sel prêt à l'emploi (chaîne). Renvoie le hachage via le callback.
Exemple :
bcrypt.hash('password123', 12, (err, hash) => {
if (err) throw err;
console.log(hash); // $2b$12$...
});
4.2. bcrypt.hashSync(data, saltOrRounds)
Signature : bcrypt.hashSync(data: string | Buffer, saltOrRounds: number | string): string
Fonction : Version synchrone de bcrypt.hash(). Bloque le thread principal jusqu'à ce que le hachage soit calculé. À utiliser avec précaution dans les applications Node.js pour éviter de bloquer le thread principal.
Exemple :
const hash = bcrypt.hashSync('password123', 10);
console.log(hash); // $2b$10$...
4.3. bcrypt.compare(data, encrypted, callback)
Signature : bcrypt.compare(data: string | Buffer, encrypted: string, callback: (err: Error | null, same: boolean) => void): void
Fonction : Compare de manière asynchrone une chaîne en clair avec un hachage. Renvoie true si elles correspondent, false sinon. Extrait automatiquement le sel et le facteur de coût du hachage.
Exemple :
bcrypt.compare('password123', hash, (err, result) => {
if (err) throw err;
console.log(result); // true ou false
});
4.4. bcrypt.compareSync(data, encrypted)
Signature : bcrypt.compareSync(data: string | Buffer, encrypted: string): boolean
Fonction : Version synchrone de bcrypt.compare(). Renvoie directement true ou false.
Exemple :
const match = bcrypt.compareSync('password123', hash);
console.log(match); // true ou false
4.5. bcrypt.genSalt(rounds, callback)
Signature : bcrypt.genSalt(rounds: number, callback: (err: Error | null, salt: string) => void): void
Fonction : Génère un sel de manière asynchrone avec le nombre de rounds spécifié. Le sel est une chaîne au format $2b$[rounds]$[salt]. Généralement, vous n'avez pas besoin d'appeler cette méthode directement, car bcrypt.hash() la gère automatiquement.
Exemple :
bcrypt.genSalt(12, (err, salt) => {
if (err) throw err;
console.log(salt); // $2b$12$...
});
4.6. bcrypt.genSaltSync(rounds)
Signature : bcrypt.genSaltSync(rounds: number): string
Fonction : Version synchrone de bcrypt.genSalt(). Renvoie directement le sel.
Exemple :
const salt = bcrypt.genSaltSync(10);
console.log(salt); // $2b$10$...
4.7. bcrypt.getRounds(encrypted)
Signature : bcrypt.getRounds(encrypted: string): number
Fonction : Extrait le nombre de rounds d'un hachage Bcrypt. Utile pour vérifier le facteur de coût utilisé.
Exemple :
const rounds = bcrypt.getRounds(hash);
console.log(rounds); // 10
4.8. bcrypt.getSalt(encrypted)
Signature : bcrypt.getSalt(encrypted: string): string
Fonction : Extrait le sel d'un hachage Bcrypt. Utile pour le débogage ou l'analyse.
Exemple :
const salt = bcrypt.getSalt(hash);
console.log(salt); // $2b$10$...
5. Exemple complet : inscription et connexion
Voici un exemple complet illustrant l'utilisation de Bcrypt dans un scénario d'inscription et de connexion utilisateur :
const bcrypt = require('bcrypt');
// Simulation d'une base de données utilisateur
const users = [];
// Fonction d'inscription
async function registerUser(email, password) {
try {
const saltRounds = 12;
const hash = await bcrypt.hash(password, saltRounds);
users.push({ email, passwordHash: hash });
console.log(`Utilisateur ${email} inscrit avec succès`);
} catch (err) {
console.error('Erreur lors de l\'inscription :', err);
}
}
// Fonction de connexion
async function loginUser(email, password) {
try {
const user = users.find(u => u.email === email);
if (!user) {
console.log('Utilisateur non trouvé');
return false;
}
const match = await bcrypt.compare(password, user.passwordHash);
if (match) {
console.log(`Connexion réussie pour ${email}`);
return true;
} else {
console.log('Mot de passe incorrect');
return false;
}
} catch (err) {
console.error('Erreur lors de la connexion :', err);
return false;
}
}
// Test
(async () => {
await registerUser('user@example.com', 'securePassword456!');
await loginUser('user@example.com', 'securePassword456!'); // Succès
await loginUser('user@example.com', 'wrongPassword'); // Échec
})();
6. Bonnes pratiques et recommandations
- Utilisez toujours un facteur de coût adapté : Pour la plupart des applications, un cost de 10 à 12 est recommandé. Ajustez en fonction des performances de votre serveur.
- Préférez les versions asynchrones : Utilisez
bcrypt.hash()etbcrypt.compare()plutôt que leurs équivalents synchrones pour ne pas bloquer le thread principal de Node.js. - Ne stockez jamais les mots de passe en clair : Même dans les logs ou les messages d'erreur, ne révélez jamais le mot de passe original.
- Utilisez HTTPS : Bcrypt protège les mots de passe au repos, mais vous devez également sécuriser leur transmission avec TLS/SSL.
- Mettez à jour régulièrement : Augmentez progressivement le facteur de coût à mesure que la puissance de calcul augmente.
- Testez les performances : Mesurez le temps de hachage sur votre serveur pour trouver le meilleur équilibre entre sécurité et expérience utilisateur.
7. Conclusion
Bcrypt est la solution de référence pour le hachage sécurisé des mots de passe dans les applications Node.js. Sa conception adaptative, son intégration automatique du sel et sa résistance aux attaques par force brute en font un choix fiable pour les développeurs soucieux de la sécurité. En suivant les bonnes pratiques présentées dans ce guide, vous pouvez protéger efficacement les données sensibles de vos utilisateurs.
N'oubliez pas : la sécurité est un processus continu. Restez informé des évolutions et mettez régulièrement à jour vos méthodes de protection.
Aussi dans la bibliothèque
Client HTTP pour Java : aperçu des meilleures bibliothèques (Java 11, Apache, OkHttp, Retrofit)
Bibliothèque standard Kotlin : aperçu complet
Elasticsearch .NET pour C# : guide complet avec exemples
Jetons JWT en Rust : bibliothèque jsonwebtoken et gestion de l'authentification