Sur la base des autres réponses à cette question, j'ai mis en place une nouvelle approche utilisant bcrypt.
Pourquoi utiliser bcrypt
Si je comprends bien, l'argument pour utiliser bcrypt
sur SHA512
c'est que bcrypt
est conçu pour être lent. bcrypt
dispose également d'une option permettant d'ajuster la vitesse à laquelle vous souhaitez qu'il soit lent lors de la génération du mot de passe haché pour la première fois :
# The '12' is the number that dictates the 'slowness'
bcrypt.hashpw(password, bcrypt.gensalt( 12 ))
La lenteur est souhaitable car si une partie malveillante met la main sur la table contenant les mots de passe hachés, il est alors beaucoup plus difficile de les forcer par force brute.
Mise en œuvre
def get_hashed_password(plain_text_password):
# Hash a password for the first time
# (Using bcrypt, the salt is saved into the hash itself)
return bcrypt.hashpw(plain_text_password, bcrypt.gensalt())
def check_password(plain_text_password, hashed_password):
# Check hashed password. Using bcrypt, the salt is saved into the hash itself
return bcrypt.checkpw(plain_text_password, hashed_password)
Notes
J'ai pu installer la bibliothèque assez facilement dans un système linux en utilisant :
pip install py-bcrypt
Cependant, j'ai eu plus de mal à l'installer sur mes systèmes Windows. Il semble avoir besoin d'un correctif. Voir cette question sur Stack Overflow : py-bcrypt s'installe sur win 7 64bit python
0 votes
Pourquoi encodez-vous le sel en b64 ? Il serait plus simple d'utiliser directement le sel et de coder les deux ensemble en b64.
t_sha.digest() + salt
. Vous pouvez à nouveau séparer le sel plus tard lorsque vous avez décodé le mot de passe salé, car vous savez que le mot de passe haché décodé est exactement de 32 octets.1 votes
@Duncan - J'ai encodé le sel en base64 pour pouvoir effectuer des opérations fortes sur celui-ci sans avoir à me soucier de problèmes bizarres. La version "bytes" fonctionnera-t-elle comme une chaîne de caractères ? Si c'est le cas, alors je n'ai pas besoin de coder en base64 t_sha.digest() non plus. Je n'enregistrerais probablement pas le mot de passe haché et le sel ensemble, car cela semble un peu plus compliqué et un peu moins lisible.
0 votes
Si vous utilisez Python 2.x, l'objet bytes fonctionnera parfaitement comme une chaîne de caractères. Python n'impose aucune restriction sur ce que vous pouvez avoir dans une chaîne de caractères. Toutefois, il n'en va pas de même si vous transmettez la chaîne à un code externe tel qu'une base de données. Python 3.x fait la distinction entre les types d'octets et les chaînes de caractères. Dans ce cas, vous ne voudrez pas utiliser les opérations de chaîne de caractères sur le sel.
6 votes
Je ne peux pas vous dire comment le faire en python, mais le simple SHA-512 est un mauvais choix. Utilisez un hachage lent tel que PBKDF2, bcrypt ou scrypt.
1 votes
Remarque : je vous déconseille d'utiliser les UUID comme source d'aléa cryptographique. Oui, l'implémentation utilisée par CPython est cryptographiquement sécurisé mais ce n'est pas dicté par les spécifications de Python. ni la spécification UUID y des mises en œuvre vulnérables existent . Si votre base de données est exécutée à l'aide d'une implémentation Python sans UUID4 sécurisés, vous aurez affaibli votre sécurité. Il s'agit d'un scénario peu probable, mais l'utilisation de
secrets
à la place.