How Password Hashing Works
Why your password isn't stored as plain text - and what actually happens instead.
Every few months, another company announces a data breach. Millions of accounts compromised. If you've ever wondered what determines whether that breach is a minor inconvenience or a total disaster, the answer is password hashing.
Why Not Just Store Passwords?
The simplest approach would be storing passwords directly in a database. User types "hunter42", you save "hunter42", and you compare them at login. This works right up until someone gains access to your database - and then every single password is immediately exposed.
Database breaches happen constantly. SQL injection, misconfigured backups, insider threats, compromised credentials. If you store plain text passwords, a single breach means every account is compromised instantly.
One-Way Functions
Hashing solves this with a one-way function. You feed in a password and get back a fixed-length string of characters. The critical property: you can't reverse it. Given the hash output, there's no mathematical way to compute the original input.
At login, you hash whatever the user typed and compare it to the stored hash. If they match, the password was correct. You never need to know or store the actual password.
Not All Hashes Are Equal
MD5 - Broken. Produces collisions (different inputs giving the same hash). Also extremely fast, which is actually bad for password hashing. Don't use it for passwords. Don't use it for anything security-related.
SHA-256 - Cryptographically strong, but too fast for passwords. A modern GPU can compute billions of SHA-256 hashes per second. An attacker with your database can try every common password in minutes.
bcrypt - Designed specifically for passwords. It's intentionally slow - you can configure how slow with a "cost factor." A cost of 12 means each hash takes roughly 250ms. That's imperceptible at login but makes brute-force attacks impractical. It also includes a built-in salt.
scrypt - Similar philosophy to bcrypt but also requires significant memory, making GPU-based attacks harder. Good choice for new systems.
Argon2 - Winner of the Password Hashing Competition (yes, that's a real thing). Configurable for time, memory, and parallelism. The current best practice for new applications.
Why Slow Is Good
This is counterintuitive. We usually want things fast. But for password hashing, slow is the entire point.
Your legitimate users hash one password at login. An attacker needs to hash billions of guesses. If each hash takes 250ms, a billion attempts take about 8 years. If each hash takes 1 nanosecond (like SHA-256 on a GPU), a billion attempts take 1 second.
Salt: Preventing Rainbow Tables
A rainbow table is a precomputed lookup of common passwords and their hashes. If you hash "password123" with plain SHA-256, the result is always the same. An attacker can build a table of millions of common passwords and their hashes, then just look up matches.
A salt fixes this. It's a random string generated for each user, prepended to the password before hashing. "password123" with salt "x7K9m" produces a completely different hash than "password123" with salt "p2Qn4". The salt is stored alongside the hash - it's not secret. Its job is to make precomputation useless.
bcrypt, scrypt, and Argon2 all handle salting automatically. You don't need to manage it yourself.
When a Database Leaks
With proper hashing (bcrypt/Argon2 + unique salts), a database breach is bad but not catastrophic. Attackers get hashes they can't reverse. They can try to crack individual passwords through brute force, but the slow hash function limits them to maybe a few thousand guesses per second per hash.
Users with strong, unique passwords are safe. Users with "password123" will eventually be cracked, but it takes time and resources per account rather than being instant for everyone.
With plain text or fast hashes? Every account is immediately compromised. All of them. At once.
Try It Yourself
See hashing in action with the Hash Generator tool - compute MD5, SHA-1, SHA-256, and SHA-512 hashes right in your browser.