Password hashing done right
Passwords are never stored. Hashes are. A good hash is slow enough that brute force is expensive, unique per user so the same password produces different hashes, and forward-compatible so you can crank the cost later without breaking existing accounts. PBKDF2-HMAC-SHA256 gives us all three.
def _hash_password(self, password: str, salt: str) -> str:
return hashlib.pbkdf2_hmac(
"sha256",
password.encode(),
salt.encode(),
PBKDF2_ITERATIONS, # 100_000
).hex()
def _generate_salt(self) -> str:
return secrets.token_hex(16) # 32 hex chars, 128 bits of entropy
Three things matter: the algorithm, a unique per-user salt generated with a cryptographically secure RNG, and an iteration count that makes each hash take real CPU time.
Flashcards: Flashcards
Loading practice…
Quiz: Quiz
Loading practice…