Why passwords are hashed, not encrypted
Encryption is a two-way street with a key. Hashing is a one-way mathematical trapdoor. Why speed is the enemy of secure passwords.
If you ever see a service email you your original password, delete your account immediately. It means they either stored it in plaintext or encrypted it with a reversible key.
Passwords must never be encrypted. They must be hashed.
Encryption vs Hashing
The difference is direction:
- Encryption (Two-way): Takes plaintext and a secret key, turns it into ciphertext, and can decrypt it back into plaintext using the key.
- Hashing (One-way): Takes plaintext, runs it through a cryptographic mathematical function, and outputs a fixed-length string (digest). It is computationally infeasible to reverse.
Encryption: Password + Secret Key <───────> Ciphertext (Reversible)
Hashing: Password + Salt ────────> Hash Value (One-way)
When a user logs in, your server does not decrypt their saved password. It hashes the password they just typed and checks whether the new hash matches the stored hash.
Why MD5 and SHA-256 are dangerous for passwords
Algorithms like MD5, SHA-1, and SHA-256 were designed for integrity checksums and high-throughput data pipelines. They are intentionally fast.
Modern GPUs can calculate billions of SHA-256 hashes per second. If an attacker dumps your database, a fast hash algorithm allows them to run brute-force and dictionary attacks across billions of common passwords in seconds.
The three pillars of secure password storage
-
Salt (Uniqueness): A random string generated per user and prepended to the password before hashing. This defeats Rainbow Tables (precomputed tables of hash lookups) and ensures two users with the password
Password123end up with completely different hashes. -
Cost Factor / Work Factor (Deliberate Slowness): Password hashing algorithms like bcrypt, Argon2id, or scrypt allow setting an iteration count or memory parameter. Hashing should take ~100–300ms on your server. To a user logging in once, 200ms is unnoticeable. To an attacker trying 100 billion combinations, 200ms per attempt makes brute forcing mathematically impossible.
-
Memory Hardness: Algorithms like Argon2id require dedicated RAM to compute, preventing attackers from mass-parallelizing attacks on custom ASIC hardware.
# A modern bcrypt hash contains algorithm version, cost, salt, and hash:
$2b$12$e8N8F3hN5lV8Y3e7u9K6q.O9m8n7b6v5c4x3z2a1s0d9f8g7h6j5k
└──┬──┘└──┬──┘└─────────┬─────────┘└─────────────┬─────────────┘
Algo Cost Salt (22 chars) Hash (31 chars)
Recommended defaults today
| Algorithm | Status | Recommendation |
|---|---|---|
| Argon2id | Gold Standard | Winner of the Password Hashing Competition; best resistance against GPU/ASIC attacks |
| bcrypt | Battle-tested | Excellent default with cost >= 12 |
| scrypt | Strong | Memory-hard, widely supported |
| SHA-256 / MD5 | Insecure for Passwords | Fast hashing makes brute-forcing trivial; never use for credentials |
Test Your Understanding
Quick architectural scenario challenge based on this breakdown.
A 3rd-party payment gateway starts timing out with 504 errors during peak traffic.
Q1.How should a downstream dependency failure be handled to protect upstream service availability?
Comments –
Sign in to share your thoughts
Nothing yet. Be the first.