Passwords & How They're Stored
When someone creates an account on a website, what does the server actually store? The answer is not the password itself — and understanding why is foundational to web security.
What is hashing?
A hash function is a mathematical operation that takes any input — a word, a password, an entire file — and produces a fixed-length string of random-looking characters. It works like a one-way process: the input goes in, a scrambled output comes out, and there is no way to reverse the output back to the original input.
Two important properties of hash functions:
- One-way — you can turn a password into a hash, but you cannot turn a hash back into the password. There's no "decrypt" button.
- Deterministic — the same input always produces the same output. "hunter2" will always produce that same MD5 hash, on any computer, anywhere in the world.
MD5 and SHA-256 — common hash functions
MD5 was invented in 1991. It was used everywhere — file verification, passwords, certificates. The problem: it's extremely fast. A modern GPU can compute billions of MD5 hashes per second. For files, fast is fine. For passwords, fast is a disaster — an attacker can try every possible combination at incredible speed.
SHA-256 is newer and more secure, but it's still a general-purpose hash function. It's still too fast for passwords. It's the right choice for verifying file integrity (e.g. checking a download hasn't been tampered with), but not for storing passwords.
Rainbow tables — how attackers crack hashes
If MD5("hunter2") always equals the same hash, an attacker can just build a massive pre-computed table: a list of millions of common passwords and their MD5 hashes. This is called a rainbow table. When they steal a database of MD5 hashes, they look each one up in their table. If the hash matches, they instantly know the password — no guessing required.
Sarah's password = hunter2
Salting — the fix for rainbow tables
A salt is a random string that's generated for each user and added to their password before hashing. So instead of hashing "hunter2", the server hashes "hunter2xK9#mQ" (where xK9#mQ is Sarah's unique random salt).
Now even if two users have the same password, they get different hashes. And the attacker's pre-built rainbow table is useless — they'd have to rebuild it for every possible salt, which is computationally impossible.
bcrypt — the right tool for passwords
bcrypt was designed specifically for storing passwords. Unlike MD5 or SHA-256, it's intentionally slow — each hash takes about 0.1 to 1 second to compute. It also has a "cost factor" you can increase as computers get faster, to keep it slow. It includes the salt built-in. This is why you see it everywhere in secure applications.
A practical indicator: if a website's "forgot password" feature emails the actual password (not a reset link), the password is stored in plaintext. The entire user database is exposed in any breach.
A site sends you your password in a "forgot password" email (not a reset link). What does this tell you?
What is the purpose of a "salt" in password hashing?