Si je comprends bien, la meilleure pratique pour générer des sels est d'utiliser une formule cryptique (ou même une constante magique) stockée dans votre code source.
Je travaille sur un projet que nous prévoyons de publier en open source, mais le problème est qu'avec la source vient la formule secrète pour générer des sels, et donc la possibilité d'exécuter des attaques de table Rainbow sur notre site.
Je pense que beaucoup de gens ont envisagé ce problème avant moi et je me demande quelle est la meilleure pratique. Il me semble qu'il ne sert à rien d'avoir du sel si le code est open source, car les sels peuvent être facilement reconstitués.
Pensées?
Les sels doivent vraiment être uniques pour chaque entrée. Même si l'attaquant peut calculer ce qu'est le sel, cela rend la table Rainbow extrêmement difficile à créer. Cela est dû au fait que le sel est ajouté au mot de passe avant d'être haché, il ajoute donc effectivement au nombre total d'entrées que la table Rainbow doit contenir pour avoir une liste de toutes les valeurs possibles pour un champ de mot de passe.
Étant donné que les questions sur le hachage du sel se posent assez régulièrement et qu'il semble y avoir une certaine confusion sur le sujet, j'ai étendu cette réponse.
Un sel est un random ensemble d'octets de longueur fixe qui est ajouté à l'entrée d'un algorithme de hachage.
L'ajout d'un sel aléatoire à un hachage garantit que le même mot de passe produira de nombreux hachages différents. Le sel est généralement stocké dans la base de données, avec le résultat de la fonction de hachage. Saler un hachage est bon pour plusieurs raisons:
Un sel n'est pas une clé secrète, mais un sel "fonctionne" en rendant la fonction de hachage spécifique à chaque instance. Avec le hachage salé, il n'y a pas un fonction de hachage, mais un pour chaque valeur de sel possible. Cela empêche l'attaquant d'attaquer [~ # ~] n [~ # ~] haché les mots de passe pour moins de [~ # ~] n [~ # ~] = fois le coût d'attaquer un mot de passe. C'est le point du sel.
Un "sel secret" n'est pas un sel, il est appelé une "clé", et cela signifie que vous ne calculez plus un hachage, mais un Message Authentication Code (MAC) . Le calcul de MAC est une entreprise délicate (beaucoup plus difficile que de simplement associer une clé et une valeur dans une fonction de hachage) et c'est un sujet très différent.
Le sel doit être aléatoire pour chaque instance dans laquelle il est utilisé. Cela garantit qu'un attaquant doit attaquer chaque hachage salé séparément.
Si vous comptez que votre sel (ou algorithme de salage) est secret, vous entrez dans les domaines de La sécurité par l'obscurité (ne fonctionnera pas). Très probablement, vous n'obtenez pas de sécurité supplémentaire du secret du sel; vous obtenez juste le sentiment flou chaleureux de sécurité. Ainsi, au lieu de rendre votre système plus sécurisé, cela vous distrait simplement de la réalité.
Techniquement, le sel doit être unique. Le point du sel doit être distinct pour chaque mot de passe haché. Cela signifie dans le monde entier. Puisqu'il n'y a pas d'organisation centrale qui distribue des sels uniques à la demande, nous devons compter sur la meilleure chose suivante, qui est la sélection aléatoire avec un générateur aléatoire imprévisible, de préférence dans un espace salin suffisamment grand pour rendre les collisions improbables (deux cas utilisant le même valeur de sel).
Il est tentant d'essayer de dériver un sel de certaines données qui sont "vraisemblablement uniques", telles que l'ID utilisateur, mais de tels schémas échouent souvent en raison de certains détails désagréables:
Si vous utilisez par exemple l'ID utilisateur , certains méchants, attaquant des systèmes distincts, peuvent simplement regrouper leurs ressources et créer des tables précalculées pour les ID utilisateur 1 à 50 . Un ID utilisateur est unique à l'échelle du système mais pas dans le monde entier.
La même chose s'applique au nom d'utilisateur : il y a une "racine" par système Unix, mais il y a beaucoup de racines dans le monde. Une table arc-en-ciel pour "racine" en vaudrait la peine, car elle pourrait être appliquée à des millions de systèmes. Pire encore, il existe également de nombreux "bob", et beaucoup n'ont pas de formation d'administrateur système: leurs mots de passe peuvent être assez faibles.
L'unicité est également temporelle. Parfois, les utilisateurs modifient leur mot de passe. Pour chaque nouveau mot de passe , un nouveau sel doit être sélectionné. Sinon, un attaquant a obtenu le hachage de l'ancien mot de passe et le hachage du nouveau pourrait essayer d'attaquer les deux simultanément.
Utiliser un sel aléatoire obtenu à partir d'un cryptogramme sécurisé et imprévisible PRNG peut être une sorte de surpuissance, mais au moins il prouvablement vous protège contre tous ces dangers. Il ne s'agit pas d'empêcher l'attaquant de savoir ce qu'est un sel individuel, il ne s'agit pas de leur donner la grosse cible grasse qui sera utilisée sur un nombre substantiel de cibles potentielles. La sélection aléatoire rend les cibles aussi fines que possible.
Utilisez un sel aléatoire, uniformément réparti et à haute entropie. Utilisez un nouveau sel chaque fois que vous créez un nouveau mot de passe ou modifiez un mot de passe. Stockez le sel avec le mot de passe haché. Privilégiez les gros sels (au moins 10 octets, de préférence 16 ou plus).
Un sel ne transforme pas un mauvais mot de passe en un bon mot de passe. Il s'assure simplement que l'attaquant paiera au moins le prix d'attaque du dictionnaire pour chaque mauvais mot de passe qu'il brise.
Sources utiles:
stackoverflow.com: Sel non aléatoire pour les hachages de mot de passe
Bruce Schneier: Cryptographie pratique (livre)
Matasano Security: Assez avec les Rainbow Tables
senix.org: La crypte Unix utilise le sel depuis 1976
owasp.org : Pourquoi ajouter du sel
openwall.com : Sels
Avis de non-responsabilité:
Je ne suis pas un expert en sécurité. (Bien que cette réponse ait été revue par Thomas Pornin )
Si l'un des professionnels de la sécurité trouve quelque chose de mal, veuillez commenter ou modifier cette réponse wiki.
Depuis qu'Unix est devenu populaire, la bonne façon de stocker un mot de passe a été d'ajouter une valeur aléatoire (le sel) et de la hacher. Conservez le sel où vous pourrez vous y rendre plus tard, mais où vous espérez que les méchants ne l'obtiendront pas.
Cela a de bons effets. Tout d'abord, les méchants ne peuvent pas simplement faire une liste des mots de passe attendus comme "Password1", les hacher dans une table Rainbow et parcourir votre fichier de mots de passe à la recherche de correspondances. Si vous avez un bon sel à deux octets, ils doivent générer 65 536 valeurs pour chaque mot de passe attendu, ce qui rend la table Rainbow beaucoup moins pratique. Deuxièmement, si vous pouvez garder le sel des méchants qui consultent votre fichier de mot de passe, vous avez rendu beaucoup plus difficile le calcul des valeurs possibles. Troisièmement, vous avez rendu impossible pour les méchants de déterminer si une personne donnée utilise le même mot de passe sur différents sites.
Pour ce faire, vous générez un sel aléatoire. Cela devrait générer chaque nombre dans la plage souhaitée avec une probabilité uniforme. Ce n'est pas difficile; un simple générateur de nombres aléatoires congruentiels linéaires fera l'affaire.
Si vous avez des calculs compliqués pour faire le sel, vous vous trompez. Si vous le calculez en fonction du mot de passe, vous le faites mal. Dans ce cas, tout ce que vous faites est de compliquer le hachage et de ne pas ajouter de sel sur le plan fonctionnel.
Personne de bon en sécurité ne compterait sur la dissimulation d'un algorithme. La cryptographie moderne est basée sur des algorithmes qui ont été largement testés, et pour être testés de manière approfondie, ils doivent être bien connus. En règle générale, il a été jugé plus sûr d'utiliser des algorithmes standard plutôt que de rouler les siens et en espérant que ce soit bon. Peu importe si le code est open source ou non, il est souvent possible pour les méchants d'analyser ce que fait un programme.
Vous pouvez simplement générer un sel aléatoire pour chaque enregistrement lors de l'exécution. Par exemple, supposons que vous stockiez des mots de passe utilisateur hachés dans une base de données. Vous pouvez générer une chaîne aléatoire de 8 caractères de caractères alphanumériques minuscules et majuscules au moment de l'exécution, ajouter celle-ci au mot de passe, hacher que chaîne et la stocker dans la base de données. Puisqu'il y a 628 les sels possibles, générer des tables Rainbow (pour chaque sel possible) coûteront trop cher; et puisque vous utilisez un sel unique pour chaque enregistrement de mot de passe, même si un attaquant a généré quelques tables Rainbow correspondantes, il ne pourra toujours pas cracker chaque mot de passe.
Vous pouvez modifier les paramètres de votre génération de sel en fonction de vos besoins de sécurité; par exemple, vous pouvez utiliser un sel plus long ou générer une chaîne aléatoire contenant également des signes de ponctuation pour augmenter le nombre de sels possibles.
Dans le cas d'une application de bureau qui crypte des données et les envoie sur un serveur distant, comment envisagez-vous d'utiliser un sel différent à chaque fois?
En utilisant PKCS # 5 avec le mot de passe de l'utilisateur, il a besoin d'un sel pour générer une clé de cryptage, pour crypter les données. Je sais que garder le sel codé en dur (obscurci) dans l'application de bureau n'est pas une bonne idée.
Si le serveur distant ne doit JAMAIS connaître le mot de passe de l'utilisateur, est-il possible d'utiliser un sel différent à chaque fois? Si l'utilisateur utilise l'application de bureau sur un autre ordinateur, comment pourra-t-il décrypter les données sur le serveur distant s'il ne possède pas la clé (elle n'est pas codée en dur dans le logiciel)?
Utilisez un générateur de fonctions aléatoires pour générer le sel et stockez-le dans la base de données, créez un sel par ligne et stockez-le dans la base de données.
J'aime la façon dont le sel est généré lors de l'inscription à Django. Référence: http://bitbucket.org/ubernostrum/Django-registration/src/tip/registration/models.py#cl-85
salt = sha_constructor(str(random.random())).hexdigest()[:5]
activation_key = sha_constructor(salt+user.username).hexdigest()
return self.create(user=user,
activation_key=activation_key)
Il utilise une combinaison de sha générée par un nombre aléatoire et le nom d'utilisateur pour générer un hachage.
Sha
lui-même est bien connu pour être solide et incassable. Ajoutez plusieurs dimensions pour générer le sel lui-même, avec un nombre aléatoire, sha et le composant spécifique à l'utilisateur, vous avez une sécurité incassable!