Question:
Est-il prudent / sage de stocker un sel dans le même champ que le mot de passe haché?
PenumbraBrah
2018-04-06 19:26:27 UTC
view on stackexchange narkive permalink

En utilisant Argon2 pour le hachage des mots de passe dans mon application, j'ai remarqué qu'il génère une chaîne comme celle-ci (par exemple pour le mot de passe "rabbit"):

  $ argon2i $ v = 19 $ m = 65536, t = 3, p = 1 $ YOtX2 // 7NoD / owm8RZ8llw == $ fPn4sPgkFAuBJo3M3UzcGss3dJysxLJdPdvojRF20ZE =  

Ma compréhension est que tout avant p = paramètres, le corps du p = est le sel, et la dernière partie est le mot de passe haché.

Est-il acceptable de stocker ceci dans un champ dans une base de données SQL ( varchar (99) dans ce cas), ou la chaîne doit-elle être séparée en ses parties constituantes? Dois-je stocker le sel séparément du mot de passe haché et conserver les paramètres dans le code?

[très fortement lié] (https://security.stackexchange.com/questions/17421/how-to-store-salt)
Si vous utilisez un [_pepper_] (https://security.stackexchange.com/questions/3272/password-hashing-add-salt-pepper-or-is-salt-enough), vous pouvez le stocker en dehors de la base de données.
La fonction PHP [password_hash] (http://php.net/manual/en/function.password-hash.php) stocke également le sel avec la chaîne hachée (par exemple: `$ 2y $ 10 $ .vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAG1`a3Fyk)
"varchar (99)" semble terriblement serré.Et si la prochaine version de la bibliothèque de hachage ajoutait des paramètres ou allongeait le hachage?Votre base de données n'a-t-elle pas "varchar (MAX)" ou similaire?
Sept réponses:
Anders
2018-04-06 19:36:50 UTC
view on stackexchange narkive permalink

Vous devez le stocker dans un seul champ. N'essayez pas de le diviser en plusieurs parties.

Je sais que cela peut sembler un peu peu intuitif pour les personnes venant d'un arrière-plan de base de données, où le modus operandi est de normaliser les données et d'utiliser des chaînes sérialisées est considéré comme un horrible hack. Mais du point de vue de la sécurité, c'est parfaitement logique.

Pourquoi? Parce que la plus petite unité sur laquelle le développeur individuel a besoin pour fonctionner est cette chaîne complète. C'est ce que l'application doit transmettre à la bibliothèque de hachage pour vérifier si un mot de passe fourni est correct ou non. Du point de vue des développeurs, la bibliothèque de hachage peut être une boîte noire, et elle n'a pas besoin de se préoccuper de ce que ces éléments embêtants signifient réellement.

C'est une bonne chose, car la plupart des développeurs sont des humains imparfaits (je sais , parce que j'en suis moi-même). Si vous les laissez séparer cette ficelle, puis essayez de la réassembler, ils vont probablement tout gâcher, comme donner à tous les utilisateurs le même sel ou pas du tout.

Seul le stockage des paramètres dans le code est également une mauvaise idée. À mesure que les processeurs s'accélèrent, vous souhaiterez peut-être augmenter le facteur de coût à l'avenir. Pendant la phase de migration, différents mots de passe auront des facteurs de coût différents. Vous aurez donc besoin d'informations sur le niveau du mot de passe pour savoir quel facteur de coût a été utilisé pour le hacher.

De nombreuses bibliothèques cryptographiques prennent le secret et le sel comme paramètres séparés.De ce seul point de vue, il semble prudent de stocker le digest et le sel / entropie dans des champs séparés.Si vous les stockez séparément, vous n'avez même pas besoin d'utiliser une longueur uniforme pour le sel.Vous pouvez faire évoluer vos algorithmes et en prendre en charge plusieurs à la fois, ce qui vous permet de pousser en douceur les utilisateurs vers un algorithme plus récent et plus puissant sans même nécessiter de changement de mot de passe, etc.
@Craig Beaucoup de bibliothèques plus anciennes le font, mais je dirais que c'est considéré comme une mauvaise conception de nos jours.En ce qui concerne les algorithmes de contrôle de version, vous pouvez également le faire avec la chaîne complète dans une colonne.
C'est pourquoi j'adore l'échange de piles.Chaque jour, j'apprends quelque chose que je ne savais pas que je ne savais pas.
Ce n'est pas seulement du point de vue des pratiques de sécurité que cela a du sens.Cela a toujours du sens du point de vue de la normalisation compte tenu des raisons que vous exposez.
Cela a également l'avantage d'être à l'épreuve du temps;si vous décidez de modifier les paramètres de hachage plus tard, les anciens hachages dans la base de données continueront à fonctionner _ (tant que vous utilisez les fonctions de la bibliothèque pour comparer les hachages, comme vous êtes censé le faire avec Argon2, plutôt que de comparer directement les chaînes de hachage) _
@Anders À quelle bibliothèque pensez-vous prendre en charge la gestion des versions du mot de passe stocké avec un seul champ de mot de passe?Je peux voir comment le faire fonctionner et l'approche a tout à fait le charme, mais je n'en ai jamais vu dans la nature.
@Voo N'importe quelle bibliothèque.Toutes les informations dont vous avez besoin - algorithme, paramètres, sel - se trouvent dans la chaîne que vous stockez dans une seule colonne.
@Anders Ce n'est plus vraiment une boîte noire si je dois définir mon propre format pour savoir comment stocker les parties séparées dans une seule chaîne et convertir moi-même le tuple (algorithme, hachage, sel) et la chaîne.Si quelque chose qui le rend beaucoup plus susceptible d'introduire des erreurs.Je pensais que l'idée était d'éviter que le développeur n'ait à gérer les parties séparées?
@Voo Oui, le but est de ne pas modifier la chaîne.Ne fais jamais cela.Je ne voulais pas suggérer cela.Je pense que nous nous comprenons mal.
@Voo spring-security version 5 va dans ce sens: https://docs.spring.io/spring-security/site/docs/current/reference/html/core-services.html#pe-dpe.La seule fonctionnalité que je trouve manquante est que la bibliothèque ne donne pas la possibilité à l'application de migrer le champ de mot de passe haché vers le schéma de codage par défaut (si vous ne l'utilisez pas)
Pour ceux qui recherchent un exemple de bibliothèque qui stocke de manière transparente tous les paramètres, y compris l'algorithme, dans une chaîne, et permet une mise à niveau en douceur vers des paramètres plus forts, consultez [PHP's password_ * functions] (http://php.net/password), y compris les exemples de [password_needs_rehash] (http://php.net/manual/en/function.password-needs-rehash.php).
@Voo Cette gestion des versions doit être déclenchée par le développeur, mais le décodage et le recodage sont entièrement gérés par la bibliothèque.
@Anders J'étais intéressé par les bibliothèques qui ont réellement une API qui fonctionne avec une seule chaîne au lieu du triple habituel.Vous avez besoin d'une configuration supplémentaire dans ce cas après tout.L'API de printemps est plutôt intéressante à parcourir.
-1
Machavity
2018-04-06 22:34:26 UTC
view on stackexchange narkive permalink

Ce qu'il vous manque, c'est que les hachages fonctionnent sur les données d'origine, moins la chaîne d'origine. Lorsque vous souhaitez valider une chaîne par rapport à un hachage, vous prenez la chaîne fournie, plus les données de hachage d'origine (coût, sel, etc.) et vous générez un nouveau hachage. Si le nouveau hachage correspond à l'ancien, la chaîne est alors validée (en d'autres termes, la chaîne n'est jamais déchiffrée , elle est remaniée ).

Avoir le sel ne vous aide pas à la force brute. Le sel est une partie essentielle d'un hachage de la même manière que les gobelets font partie d'une serrure. Si vous supprimez l'un ou l'autre, personne ne peut l'utiliser.

La séparation du stockage est inutile. Vous devrez réassembler le hachage terminé pour le valider dans la plupart des cas. C'est pourquoi tous les composants sont stockés dans une chaîne pratique par défaut.

Vous l'avez expliqué beaucoup plus élégamment que moi, en moins de mots.+1
Oui, séparer est inutile - vous ne pouvez pas utiliser l'un sans l'autre, vous ne mettez jamais à jour l'un sans l'autre, et ils ont des exigences de sécurité identiques, alors traitez salt + password comme une seule unité indivisible pour le stockage.
keithRozario
2018-04-06 22:00:48 UTC
view on stackexchange narkive permalink

Oui, vous pouvez le stocker dans un seul champ, et de nombreuses bases de données / applications stockent le sel + le hachage dans un seul champ / fichier etc.

Le plus célèbre est Linux (qui n'est pas un DB), qui stocke le hachage dans le fichier / etc / shadow en utilisant le format:

"$ id $ salt $ hashed", la forme imprimable d'un hachage de mot de passe tel que produit par crypt (C) , où "$ id" est l'algorithme utilisé. (Sous GNU / Linux, "$ 1 $" signifie MD5, "$ 2a $" est Blowfish, "$ 2y $" est Blowfish (gestion correcte des caractères 8 bits), "$ 5 $" est SHA-256 et "$ 6 $ "est SHA-512, [4] d'autres Unix peuvent avoir des valeurs différentes, comme NetBSD.

(source: https://en.wikipedia.org/wiki/Passwd)

Le sel n'est pas censé être secret (ou du moins pas plus secret que le hachage). Son objectif principal est de rendre les attaques par force brute beaucoup plus difficiles puisque l'attaquant doit utiliser un sel différent pour chaque utilisateur.

Mais votre question est plus nuancée - parce que vous ne posez pas seulement des questions sur les sels, mais aussi sur les paramètres. Des choses comme l'algorithme de hachage, le nombre d'itérations et le sel. cas, ne stockez pas cela dans le code, ils appartiennent toujours à la base de données.

Imaginez que vous avez un groupe d'utilisateurs et que vous avez utilisé SHA1 comme algorithme de hachage. Donc, votre champ de base de données être quelque chose comme SHA1:SALT:HASH

Si vous vouliez mettre à niveau votre base de données vers BCRYPT, comment feriez-vous cela?

Typi En général, vous déploieriez du code de sorte que lorsqu'un utilisateur se connecte, vous vérifiez le mot de passe, et s'il est valide, vous hachez à nouveau le mot de passe avec un algorithme plus récent. Maintenant, le champ de l'utilisateur ressemble à ceci: BCRYPT:SALT:HASH

Mais alors certains utilisateurs seraient sur SHA1, et d'autres sur BCRYPT, et comme il s'agit d'un niveau utilisateur, vous avez besoin des paramètres qui indiquent à votre code quels utilisateurs doivent être dans la base de données.

En bref, stocker les paramètres et le hachage dans un seul champ est OK, mais les diviser pour une raison quelconque (efficacité, code plus simple, etc.) est également OK. Ce qui ne va pas, c'est de le stocker dans votre code :)

TL:DR↑

Troy Hunt a récemment publié un podcast suggérant qu'au lieu de migrer vers BCRYPT de la manière ci-dessus, il est plus efficace de simplement prendre tous les hachages SHA1 actuellement dans la base de données, et les hacher en utilisant BCRYPT.

En fait, BCRYPT(SHA1(clear_password))

Lorsqu'un utilisateur se connecte, vous

  BCRYPT (SHA1 (clear_password)) == <db_field>  

De cette façon, tout le monde sur la plate-forme est mis à jour en même temps, et vous n'avez pas de base de données avec plusieurs hachages formats des mots de passe. Très propre et très agréable.

Je pense que cette idée est parfaitement logique, mais même si tout le monde migre en même temps, ce n'est pas instantané. À moins que vous ne vouliez accepter des temps d'arrêt sur l'application (pendant que vous hachez à nouveau tous les mots de passe), il y aura encore un petit intervalle de temps où certains utilisateurs sont sur BCRYPT et d'autres sur SHA1, par conséquent, votre base de données devrait toujours stocker le paramètres de l'algorithme de hachage, et votre code s'exécuterait en fonction de celui-ci.

Vous connaissez le truc [Pourquoi ne devrions-nous pas rouler le nôtre?] (Https://security.stackexchange.com/q/18197/114527)?Est-ce que `BCRYPT (SHA1 ())` a été * prouvé * pour ne pas avoir ce problème?(Vous n'avez pas donné de lien pour que je puisse facilement enquêter, et «fait tout à fait sens» n'est pas la même chose que «c'est vrai».)
Eh bien, j'ai mis en garde la phrase avec "Je pense", cela a un sens parfait :).Je crois comprendre que si BCRYPT fonctionne en rendant la force brute plus chère, quelle que soit l'entrée, qu'il s'agisse d'un SHA1 ou du texte clair, l'attaquant coûtera toujours plus cher à l'attaquant.Le BCRYPT (SHA1 ()) a du sens du point de vue de la migration.
J'ai également trouvé ce sujet ici, qui vous suggère d'autres cas d'utilisation pour SHA-ing un mot de passe avant BCRYPT-ing.Le consensus général sur le fil était que c'est une bonne chose à faire, mais peut-être devrions-nous commencer une question distincte si vous n'êtes toujours pas d'accord https://security.stackexchange.com/questions/61595/is-it-good-practice-to-sha512-passwords-avant-de-les-passer-à-bcrypt
@keithRozario "Il est intuitivement évident que BCRYPT (SHA1 (x)) est au moins aussi sûr que BCRYPT (x)" n'est pas la même chose que "il existe une preuve de sécurité que ...".Première règle de la cryptographie: ne faites jamais confiance à votre intuition à moins que votre nom ne soit djb ou similaire.
@MartinBonner est correct.C'est * EST * intuitif mais c'est aussi faux.Supposons que SHA1 est cassé.Simulez cela en lui faisant renvoyer 1 pour toutes les entrées.BYCRYPT (SHA1 (x)) est clairement moins sécurisé que BCRYPT (x) dans ce scénario, considérez de même SHA1 (BCRYPT (x)).Selon * comment * SHA1 est cassé le chaînage, les hachages * pourraient * rester valides.Mais ce ne sera jamais plus sûr que d'utiliser le plus sûr des deux.Puisqu'ils affectent idéalement les mêmes paramètres dans l'équation de sécurité.* Si * ils avaient un chaînage d'interaction minimal, cela pourrait être utile, mais c'est beaucoup de maths.D'où * prouvé * @ AndrewMorton
@AndrewMorton Bonne discussion, mais je ne suis pas convaincu.Votre exemple de simulation de SHA1 cassé en le faisant renvoyer 1 pour toutes les entrées n'est pas correct, c'est comme dire si l'utilisateur choisit 1 pour son mot de passe, alors BCRYPT est cassé.Mais je commence un autre fil parce que je pense que c'est intéressant.
le nouveau fil est ici: https://security.stackexchange.com/questions/183358/how-secure-is-bcryptsha1password
@keithRozario C'est Black qui a écrit ça.
TTT
2018-04-07 00:27:25 UTC
view on stackexchange narkive permalink

Du point de vue de la sécurité, peu importe si le sel et le mot de passe haché sont stockés dans un seul champ ou des champs séparés, même si je pencherais vers un seul champ pour plus de simplicité. La seule raison de les séparer est si votre code d'application doit transmettre le sel et le mot de passe séparément à la fonction de validation. Si le code de votre application ne nécessite qu'une seule chaîne combinée, vous pouvez aussi bien le stocker de cette façon.

À titre d'exemple, l'ancien abonnement ASP.NET a divisé le hachage et le sel du mot de passe en deux champs de base de données, et le La nouvelle identité ASP.NET a le hachage et le sel dans un seul champ DB, et à leur tour, les nouvelles fonctions ont été modifiées pour gérer la chaîne unique en tant qu'entrées et sorties.

Andrew Morton
2018-04-08 00:36:49 UTC
view on stackexchange narkive permalink

Est-il acceptable de stocker ceci dans un champ d'une base de données SQL (varchar (99) dans ce cas)

Non. La taille des données peut changer à un moment donné. Un champ varchar (MAX) doit être utilisé à moins que les spécifications n'indiquent que la taille sera toujours exactement 99 et qu'il n'y aura aucune variation par rapport à cela jamais . Laissez la base de données s'occuper des besoins de stockage.

ArtisticPhoenix
2018-04-08 05:42:05 UTC
view on stackexchange narkive permalink

Pour savoir si c'est plus ou moins sûr, nous devons comprendre le but d'un sel.

Un sel sert à plusieurs fins (auxquelles je peux penser)

  1. Empêcher les attaques par dictionnaire

Une attaque par dictionnaire consiste à utiliser un mot logique dans le cadre d'un mot de passe. L'archétype étant le mot password ou encore P @ ssW0rd . Les gens sont imparfaits et il leur est plus facile de se souvenir des mots, puis des chaînes aléatoires de lettres et de chiffres. Une attaque par dictionnaire s'appuie sur cela pour raccourcir le chemin d'une attaque par force brute. De toute évidence, si nous y ajoutons un morceau aléatoire de choses, cela rend ce type d'attaque impossible, ou inutile et les remet à forcer brutalement le tout.

Si un attaquant connaît le sel utilisé, il devra éditer tous ses fichiers de dictionnaire pour chaque mot de passe, et cela suppose qu'il sait comment le sel est ajouté au mot de passe d'origine. L'un des grands avantages d'une liste de dictionnaires est que vous prenez 1000 mots de passe et 1 million de mots de dictionnaire. Ensuite, vous les parcourez en essayant d'obtenir quelques correspondances sur des mots de passe plus faibles. Il n'est donc pas vraiment pratique de devoir éditer 1 million de mots 1000 fois.

  1. Empêcher les attaques de table Hash ou Rainbow.

A La table Rainbow est l'endroit où les hachages sont pré-calculés et stockés dans une sorte de base de données. Par exemple, vous pouvez prendre MD5 et commencer simplement à hacher des éléments aléatoires et à les enregistrer. Ensuite, lorsque vous voulez déchiffrer un mot de passe, il vous suffit de chercher dans le tableau arc-en-ciel.

Si un attaquant a le sel, il doit recompiler la table arc-en-ciel pour chaque sel utilisé. L'avantage de cette attaque est d'avoir ces données compilées à l'avance et de les réutiliser encore et encore. Cela les remet à forcer brutalement le mot de passe. En salant et en salant tous les mots de passe différemment, cela signifie essentiellement que vous devez recalculer la table arc-en-ciel pour chaque sel. C'est pourquoi il est important d'utiliser des sels différents pour chaque mot de passe.

Été

Aucune de ces raisons ne repose vraiment sur le fait que le sel est secret. De toute évidence, ils sont tous moins forts si un attaquant connaît le sel. Mais les informations supplémentaires qu'ils obtiennent les aideront toujours. Donc, je ne dirais pas de faire de la publicité, mais il y a un dicton sur la sécurité basée sur l'obscurité ....

Clause de non-responsabilité Je ne suis en aucun cas un expert en cryptologie, mais ce sont quelques-unes des principales raisons qui me viennent à l'esprit lorsque je pense aux sels.

J'espère que cela aide.

Vous vous trompez sur la troisième raison.Le sel est public, donc l'attaquant peut toujours utiliser tous les mots de passe à 1 caractère, tous les mots de passe à 2 caractères, etc. La * seule * chose qu'un sel fait, c'est que l'attaquant doit travailler un utilisateur à la fois,
@MartinBonner - très bien je l'ai enlevé ...
maggick
2018-04-06 19:36:48 UTC
view on stackexchange narkive permalink

Le sel n'est utilisé que pour bloquer les attaques des tables arc-en-ciel. Par conséquent, votre sel peut être stocké avec le mot de passe haché comme c'est le cas sur le système GNU / Linux le plus récent où le sel est stocké dans / etc / shadow.

Je ne sais pas comment votre réponse s'appliquerait aux différentes colonnes de la base de données?


Ce Q&R a été automatiquement traduit de la langue anglaise.Le contenu original est disponible sur stackexchange, que nous remercions pour la licence cc by-sa 3.0 sous laquelle il est distribué.
Loading...