Aller au contenu

Hasher un mot de passe avec Node.js

Vous êtes responsable des données qui transigent par votre api. Les informations sensibles comme un mot de passe doivent toujours être hashé avant d'être enregistrées dans une base de données.

Petit rappel, le hachage de mot de passe consiste à transformer un mot de passe en lettres alphanumériques à l'aide d'algorithmes spécifiques.

BCrypt

Sous Node.js vous avez la librairie BCrypt qui vous aide à hasher un mot de passe et ensuite de le valider.

Fonctionnement

On va fournir à BCrypt un mot de passe en clair qu'il va convertir en un hash. C'est cette donnée que nous allons enregistrer dans la base de données. BCrypt utilise aussi le concept de salt qui ajoute une couche supplémentaire de sécurité. Un salt est une chaine de caractère généré aléatoirement et qui sera ajouté au hash. Un autre concept utilisé est le cost factor, un indicateur du temps pris pour générer le hash. Plus le cost factor est élevé, plus le hash sera sécuritaire mais il sera plus long à générer.

Utilisation

Installation

npm install bcrypt

Pour hasher une chaine de caractère on va utiliser la fonction hash() de BCrypt. La fonction va prendre en argument la chaine de caractère à hasher ainsi que le cost factor. Le salt va étre généré automatiquement et ajouté au hash.

hashage.js
1
2
3
4
5
6
7
8
9
const bcrypt = require('bcrypt');
const costFactor = 10;
const password = "Admin@1234";

bcrypt.hash(password, costFactor)
  .then(hash => {
    console.log('Hash: ', hash)
  })
  .catch(err => console.error(err.message))

On pourrait aussi le faire en deux étapes, générer le salt et ensuite le hash.

script.js
const bcrypt = require('bcrypt');
const costFactor = 10;
const password = "Admin@1234";

bcrypt.genSalt(costFactor)
  .then(salt => {
    console.log('Salt: ', salt)
    bcrypt.hash(password, salt)
        .then((hash) => {
            console.log('Hash: ', hash)
        })
  })
  .catch(err => console.error(err.message))

À l'aide de async et await, on peut simplifier encore plus la syntaxe

1
2
3
4
5
const ajouterUtilisateur = async (req, res) => {
    // ...
    const hash = await bcrypt.hash(req.body.password, costFactor);
    // ...
}

Structure du hash

Le hash obtenu sera une chaine d'une longueur de 60 caractères sous le format $[Algorithme]$[costFactor]$[Salt/Hash].

Exemple de hash
$2b$10$MUWYJRZ4mnHGfzf1Dy.34.1cXsQfJ9d3Me1YmUYWY90F1xXnthK2q

Il est composé de 4 parties, le signe $ fait office de séparateur :

  • 2b : L'algorithme utilisé, ici le code est pour BCrypt.
  • 10 : Le cost factor
  • MUWYJRZ4mnHGfzf1Dy.34. : Les 22 caractères du salt.
  • 1cXsQfJ9d3Me1YmUYWY90F1xXnthK2q : Le hash en 31 caractères.

Comparer un mot de passe à un hash

Le mot de passe hashé ne pourra jamais être "déhashé". Pour valider un mot de passe (ou tout autre chaine de caractères) nous allons utiliser la fonction compare de BCrypt.

bcrypt.js
1
2
3
4
5
6
7
bcrypt.compare(password, hash)
.then(res => {
    // Code si vrai
})
.catch(err => {
    // code si faux
})

La fonction va utiliser les informations de l'algorythme, du cost factor et du salt pour hasher le mot de passe sous les mêmes conditions et valider qu'il correspond.

Mediagraphie