Depuis Python 3.4, le hashlib
module de la bibliothèque standard contient des fonctions de dérivation de clé qui sont «conçues pour un hachage de mot de passe sécurisé» .
Utilisez donc l'un de ceux-ci, comme hashlib.pbkdf2_hmac
, avec un sel généré en utilisant os.urandom
:
from typing import Tuple
import os
import hashlib
import hmac
def hash_new_password(password: str) -> Tuple[bytes, bytes]:
"""
Hash the provided password with a randomly-generated salt and return the
salt and hash to store in the database.
"""
salt = os.urandom(16)
pw_hash = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000)
return salt, pw_hash
def is_correct_password(salt: bytes, pw_hash: bytes, password: str) -> bool:
"""
Given a previously-stored salt and hash, and a password provided by a user
trying to log in, check whether the password is correct.
"""
return hmac.compare_digest(
pw_hash,
hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000)
)
salt, pw_hash = hash_new_password('correct horse battery staple')
assert is_correct_password(salt, pw_hash, 'correct horse battery staple')
assert not is_correct_password(salt, pw_hash, 'Tr0ub4dor&3')
assert not is_correct_password(salt, pw_hash, 'rosebud')
Notez que:
- L'utilisation d'un sel de 16 octets et 100000 itérations de PBKDF2 correspondent aux nombres minimums recommandés dans la documentation Python. Augmenter davantage le nombre d'itérations rendra vos hachages plus lents à calculer, et donc plus sécurisés.
os.urandom
utilise toujours une source aléatoire sécurisée par cryptographie
hmac.compare_digest
, utilisé dans is_correct_password
, est fondamentalement juste l' ==
opérateur pour les chaînes, mais sans la capacité de court-circuit, ce qui le rend immunisé contre les attaques de synchronisation. Cela ne fournit probablement pas vraiment de valeur de sécurité supplémentaire , mais cela ne fait pas de mal non plus, alors je suis allé de l'avant et je l'ai utilisé.
Pour la théorie sur ce qui fait un bon hachage de mot de passe et une liste d'autres fonctions appropriées pour le hachage des mots de passe avec, voir https://security.stackexchange.com/q/211/29805 .
t_sha.digest() + salt
. Vous pouvez séparer à nouveau le sel plus tard lorsque vous avez décodé le mot de passe de hachage salé, car vous savez que le mot de passe haché décodé est exactement de 32 octets.