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