Począwszy od Pythona 3.4, hashlib
moduł w bibliotece standardowej zawiera funkcje wyprowadzania kluczy, które są „zaprojektowane do bezpiecznego mieszania haseł” .
Więc użyj jednego z nich, na przykład hashlib.pbkdf2_hmac
, z solą wygenerowaną przy użyciu 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')
Zauważ, że:
- Użycie 16-bajtowej soli i 100000 iteracji PBKDF2 odpowiada minimalnym liczbom zalecanym w dokumentacji Pythona. Dalsze zwiększanie liczby iteracji spowoduje, że obliczenia skrótu będą wolniejsze, a przez to bezpieczniejsze.
os.urandom
zawsze używa kryptograficznie bezpiecznego źródła losowości
hmac.compare_digest
, używany w is_correct_password
, jest w zasadzie tylko ==
operatorem dla łańcuchów, ale bez możliwości zwarcia, co czyni go odpornym na ataki czasowe. To prawdopodobnie nie zapewnia żadnej dodatkowej wartości bezpieczeństwa , ale też nie boli, więc poszedłem do przodu i użyłem go.
Aby poznać teorię na temat tego, co składa się na dobry skrót haseł i listę innych funkcji odpowiednich do haszowania haseł, zobacz https://security.stackexchange.com/q/211/29805 .
t_sha.digest() + salt
. Możesz ponownie podzielić sól później, gdy odkodujesz solone hasło mieszające, ponieważ wiesz, że zdekodowane zaszyfrowane hasło ma dokładnie 32 bajty.