Bcrypt pour JavaScript (Node.js) : guide complet avec exemples

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

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() et bcrypt.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.

Recommendations