PROJET AUTOBLOG


BohwaZ

Site original : BohwaZ

⇐ retour index

Comment stocker les mots de passe

vendredi 29 juin 2012 à 23:27

Une seule réponse possible : avec bcrypt !

Pourquoi bcrypt ? Je ne m'étendrais pas sur le sujet, d'autres l'ont déjà fait avant moi, et mieux.

Comme dis et répété depuis longtemps par mes petits camarades (et notamment mat), c'est la seule méthode qu'on devrait utiliser. Et je suis également fautif, jusqu'à quelques années j'utilisais toujours une méthode perso à base de sha1($password . $salt) mais c'est pas pareil ! Alors pourquoi ne pas déjà le faire ? Pourquoi ne pas l'avoir déjà fait depuis longtemps ? Et bien en partie car PHP ne donne pas d'accès simple à bcrypt, qu'il faut passer par la syntaxe un peu ésotérique de crypt pour y avoir accès. Mais pas de panique, c'est quand même simple à faire. Démonstration.

Premièrement nous allons hasher notre mot de passe. Pour cela nous devons générer le salt nous-même, PHP n'ayant pas de méthode native pour le faire, donc on va se baser sur un sha1 de uniqid() qui est nourri par rand(). rand() n'est pas réputé pour être un bon générateur de hasard, il vaudrait mieux utiliser directement /dev/urandom ou openssl, mais pour un cas simple rand() devrait suffire amplement, surtout avec Suhosin qui donne à rand() une vrai capacité de générer du vrai hasard.

$salt = substr(sha1(uniqid(mt_rand(), true)), 0, 22);

Ensuite nous allons hasher le mot de passe avec le salt :

$password = crypt($password, '$2a$08$' . $salt);

Nous avons donc désormais un mot de passe hashé, que nous pouvons stocker tel quel dans la base de données par exemple. Maintenant imaginons que nous voulions vérifier ce mot de passe, par exemple après que l'utilisateur l'ait entré dans un formulaire de connexion à un site ? Et bien c'est très simple, on reprends notre $password que nous avons stocké et on le donne à crypt en second argument, qui va se charger tout seul d'en extraire le salt et renvoyer un hash. Si le hash diffère du hash stocké, c'est que le mot de passe entré est erroné.

if ($password == crypt($_POST['password'], $password))
{
    echo "Connexion réussie !";
}

Et voilà, maintenant vous n'avez plus d'excuse !