How to implement secure password hashing
· Category: Cybersecurity
Short answer
Never store plaintext passwords. Use a purpose-built password hashing algorithm like bcrypt or Argon2 with a per-user salt. These algorithms are intentionally slow, making brute-force attacks impractical. MD5 and SHA are cryptographic hashes, not password hashes — they're too fast for password storage. For the fundamentals, see how does hashing work.
Why not MD5 or SHA-256?
| Algorithm | Time to hash "password123" | Attack feasibility |
|---|---|---|
| MD5 | ~1 microsecond | 1 billion guesses/second |
| SHA-256 | ~1 microsecond | 1 billion guesses/second |
| bcrypt (cost 12) | ~250 milliseconds | ~4 guesses/second |
| Argon2id (t=3, m=64MB) | ~300 milliseconds | ~3 guesses/second |
The difference: bcrypt and Argon2 are deliberately slow. A database breach with bcrypt hashes gives attackers almost nothing.
Implementation (Python)
import bcrypt
# Hashing
password = b"user_password"
salt = bcrypt.gensalt(rounds=12)
hashed = bcrypt.hashpw(password, salt)
# Verifying
if bcrypt.checkpw(user_input.encode(), hashed):
print("Match!")
Salting
A salt is a random value added to each password before hashing. It prevents: - Rainbow table attacks: Precomputed hash tables become useless - Duplicate detection: Two users with the same password get different hashes
Tips
- Use bcrypt (cost 12+) or Argon2id — never MD5, SHA-1, or SHA-256 for passwords
- The salt is stored alongside the hash (it's not a secret, it just needs to be unique)
- Rate-limit login attempts and implement account lockout after N failures