Introduction à PBKDF2

Beaucoup d'entreprises ou de personnes isolées utilisent des fonctions de hachage comme MD5 ou SHA-1 pour protéger les données de leurs utilisateurs. Mais ces mêmes fonctions ont connu ces dernières années une mise en avant de vulnérabilités qui les rend de nos jours peu sûres.
C'est pourquoi je voulais faire un billet pour présenter PBKDF2.

Qu'est ce que PBKDF2 ?

PBKDF2 (Password-Based Key Derivation Function 2) est une fonction de dérivation de clé permettant notamment le hachage de mots de passe, mais aussi la génération de clé de chiffrement de données (associé à des fonctions comme SHA-256). Cette norme a été décrite dans la RFC 2898

Pourquoi PBKDF2 ?

PBKDF2 permet d'éviter le cassage des mots de passe par bruteforce étant donné qu'il rajoute de la complexité et complique aussi l'utilisation des tables en arc-en-ciel (rainbows tables) grâce à l'ajout d'un sel.

Les fonctions de dérivation de clés ont la qualité de pouvoir augmenter le nombre d'itérations de hachage au fur et à mesure que les processeurs deviennent de plus en plus rapide avec le temps.

À l'heure où j'écris ces lignes, le nombre d'itérations recommandées est de 10 000 (~100ms).

Pourquoi ne pas utiliser simplement une fonction comme MD5 ou SHA-1 ?

Le problème majeur des fonctions de hachage comme MD5 ou SHA-1 est qu'elles sont sensibles aux collisions (cf : https://en.wikipedia.org/wiki/Hash_function_security_summary)

Dans un prochain article je mettrai en avant une démonstration (en cours de préparation) des faiblesses MD5 et SHA-1 sur une machine moyenne.

PBKDF2 appliqué à PHP

Il existe une fonction dans PHP qui s'appelle hash_pbkdf2
Cette fonction permet de hacher un mot de passe avec un algorithme (SHA-256 par exemple) et un sel (de préférence généré aléatoirement).

Pour créer un sel aléatoire, il existe la fonction mcrypt_create_iv qui va lire soit dans /dev/random soit dans /dev/urandom selon la constante passée en paramètre de la fonction ; par défaut, si rien n'est passé en 2eme argument, la fonction va utiliser /dev/urandom (cf : http://www.onkarjoshi.com/blog/191/device-dev-random-vs-urandom/ pour connaître la différence entre /dev/random et /dev/urandom).

Exemple d'implémentation :

$salt = mcrypt_create_iv(20);
$password = $_GET['password'];
$algo = 'sha256';
$hashedPassword = hash_pbkdf2($algo, $password, $salt, 10000);

Si nous considérons que $password = "mypassword", selon l'entropie de la machine pour générer le sel, le résultat sera sous la forme suivante :

b475244ab53b80af01a3709ef8d28426d07124430cf07ad3f37d6e9e186165da
7a49f826c775806426d8497513cc2f1073fb499ac0d77c45343f9d126439f048

Note : L'algorithme SHA-256 semble, à l'heure actuelle, convenable. Pour plus de détails, https://secure.php.net/manual/fr/function.hash-algos.php

Liens externes sur le sujet :

https://blog.imirhil.fr/developpeurs-utilisateurs-comment-gerer-vos-mots-de-passe.html