Ai-je besoin d'un" sel aléatoire " une fois par mot de passe ou une seule fois par base de données?
Suite à ma question précédente sur les mots de passe salés en PHP / MySQL, j'ai une autre question concernant les sels.
Quand quelqu'un dit "utiliser un sel aléatoire" pour pré / ajouter à un mot de passe, cela signifie-t-il:
- Création d'une statique une chaîne de caractères générée aléatoirement 1 fois, ou
- Création d'une chaîne de caractères qui change au hasard à chaque fois le mot de passe est créé ?
Si le sel est aléatoire pour chaque utilisateur et stocké avec le mot de passe haché, comment le sel original est-il récupéré pour vérification?
4 réponses
Un nouveau sel devrait être généré aléatoirement pour chaque utilisateur et chaque fois qu'ils changent leur mot de passe au minimum. Ne comptez pas seulement sur un sel à l'échelle du site, par exemple, car cela défait le point d'utiliser un sel en premier lieu.
L'utilisation d'un sel unique pour chaque utilisateur est telle que si deux utilisateurs ont le même mot de passe, ils n'obtiendront pas le même hachage résultant. Cela signifie également qu'une attaque par force brute devrait être montée contre chaque utilisateur individuellement plutôt que de pouvoir pré-calculer un table arc-en-ciel pour le site.
Vous stockez ensuite le résultat du hachage du sel et du mot de passe dans la base de données hash(salt + password)
, avec le salt
pour chaque utilisateur. Vous pouvez les stocker dans des colonnes séparées, ou toutes dans une colonne (séparées par un caractère non utilisé dans les hachages, donc ;
par exemple). Tant que vous pouvez récupérer les deux, vous irez bien.
Cependant, si votre base de données est compromise, que ce soit en raison d'un accès local ou via des attaques par injection SQL, les deux le sel et le hachage final seront disponibles, ce qui signifie qu'une attaque par force brute sur les mots de passe des utilisateurs serait triviale. Pour lutter contre cela, comme suggéré par The Rook Vous pouvez également utiliser une clé secrète sitewide stockée dans un fichier localement comme une autre entrée de votre méthode de hachage afin qu'un attaquant ait également besoin de le savoir pour monter une attaque efficace. Ce qui signifie que votre base de données devrait être compromise et que l'attaquant aurait besoin d'accéder aux fichiers locaux. Donc, en utilisant hash(hash(salt + secret) + password)
, etc.
Alors que dans la plupart des algorithmes vous visez à rendre les choses aussi vite que possible, pour le hachage de mot de passe, vous voulez le ralentir, c'est ce qu'on appelle renforcement des clés (ou parfois étirement des clés). S'il faut 0,00001 secondes pour que votre fonction de hachage revienne, quelqu'un peut essayer brute forçant 100 000 mots de passe par seconde jusqu'à ce qu'ils trouvent une correspondance. S'il faut 1 seconde pour que votre fonction de hachage crache le résultat, ce n'est pas une grosse affaire en ce qui concerne quelqu'un qui se connecte à votre application, mais pour craquer le mot de passe c'est plus important puisque chaque tentative prendra maintenant 1 seconde pour obtenir un résultat, ce qui signifie qu'il faudrait 100 000 fois plus de temps pour tester chaque mot de passe forcé Brutal qu'il ne le ferait en utilisant votre fonction de hachage d'origine.
Pour ralentir votre fonction de hachage, il vous suffit de l'exécuter plusieurs fois. Par exemple, vous pourriez faire new_hash = salt + password + previous_hash
100 000 fois. Vous devrez peut-être ajuster le nombre d'itérations à une valeur plus élevée si elle est trop rapide. Si vous souhaitez pouvoir modifier la valeur ultérieurement, assurez-vous de stockez le nombre d'itérations avec l'enregistrement utilisateur afin de ne pas affecter les mots de passe précédemment stockés.
Votre enregistrement utilisateur devrait maintenant avoir un champ formaté comme ceci " $<algorithm>$<iterations>$<salt>$<hash>
"(ou en tant que champs séparés si vous le souhaitez).
Lorsque l'utilisateur entre son mot de passe, vous pouvez récupérer le sel et le nombre d'itérations de la base de données et le secret sitewide à partir d'un fichier local et valider que lorsque vous exécutez le même nombre d'itérations avec le sel et le mot de passe, le hachage résultant correspond à ce que vous avez stocké.
Si l'utilisateur change son mot de passe, alors vous devriez générer un nouveau sel.
La méthode de hachage que vous utilisez n'a pas d'importance (mais l'algorithme de hachage le fait*). Ci - dessus, j'ai suggéré hash(hash(salt + secret) + password)
mais aussi hash(hash(salt) + hash(secret) + hash(password))
. La méthode que vous utilisez ne change pas l'efficacité de votre stockage de mot de passe, l'un n'est pas vraiment plus sûr que l'autre. S'appuyant sur la conception de la façon dont vous hachez le mot de passe et le sel ensemble pour assurer la sécurité est appelée sécurité par l'obscurité et devrait être évitée.
*Vous ne devez pas utiliser MD5 ou SHA-1 car ceux-ci sont considérés comme non sécurisés. Utilisez plutôt la famille SHA-2 (SHA256, SHA512, etc.). (Ref)
La deuxième alternative est la bonne.
Traditionnellement, le sel est stocké avec le mot de passe haché, mais non crypté (généralement préappendé, par exemple dans les mots de passe unix )
Update: la méthode utilisée dans la plupart des nouveaux systèmes Unix est celle-ci.
Le sel doit être stocké avec le hachage pour que la vérification soit possible. La meilleure pratique serait d'utiliser un sel différent chaque fois qu'un mot de passe est créé ou modifié.
Changer dynamiquement le sel est beaucoup plus sûr que d'avoir un sel statique unique.
Rendent également les sels uniques par utilisateur et non pas un sel global. Changez-les chaque fois qu'un utilisateur se connecte par exemple.
Concataner le sel à la fin du mot de passe puis le hacher est OK, mais est une formule facilement devinable. Mieux vaut trouver le vôtre, c'est-à-dire tisser le sel et le mot de passe pour créer une nouvelle chaîne puis le hachage, car md5 (mot de passe + sel) est vulnérable aux attaques par dictionnaire encore.