Contents

Security › Authentication & Authorization

Password Hashing

Storing a one-way, deliberately slow fingerprint of a password instead of the password itself.

Never store passwords. Store a hash: the output of a one-way function. At login you hash what the user typed and compare it to the stored hash. If your database leaks, the attacker gets hashes, not passwords.

Not just any hash

General-purpose hashes like MD5 or SHA-256 are designed to be fast, which is exactly wrong here. A GPU can try billions of SHA-256 guesses per second, so leaked hashes of common passwords fall almost instantly.

Password hashes are designed to be slow and tunable:

AlgorithmNotes
Argon2idCurrent recommendation. Memory-hard, so GPUs don’t help much.
bcryptOlder, still fine, very widely supported. Max 72-byte input.
scryptMemory-hard, less common in practice.
MD5, SHA-1, SHA-256Not for passwords.

They also handle the salt for you; it’s stored inside the output string.

In practice

Use your framework’s or a well-known library’s function. Don’t write your own.

from argon2 import PasswordHasher
ph = PasswordHasher()

stored = ph.hash("hunter2")      # save this string
ph.verify(stored, "hunter2")     # raises on mismatch

A slow hash takes around 100 ms per login on your server: unnoticeable for one user, crippling for an attacker trying billions.