The question every interviewer asks
"How would you store user passwords?" It is asked in campus interviews for web developer roles, not only security roles. Most candidates say "encrypted". That answer is wrong, and this lesson is about why.
Encryption is reversible. Hashing is not.
Encryption is a two-way function. You put in plaintext and a key, you get ciphertext. With the key you can get the plaintext back. That is the whole point — you encrypt a message so the receiver can decrypt it.
Hashing is a one-way function. You put in any input and you get a fixed size output. There is no key and no way back. The hash of "hello" with SHA-256 is always the same 64 hex characters, and from those characters you cannot compute "hello".
Now the important part. If your database stores passwords encrypted, the decryption key is sitting somewhere on your server. Whoever steals the database usually gets the key too, and now they have every password in plaintext. If your database stores hashes, there is nothing to decrypt.
Say "hashed, not encrypted" in the interview. Answering "encrypted" is a design error, and it tells the interviewer you have not thought about what happens on the day the database is stolen.
How login works with hashes
- The user registers with the password
Rainy#Season42. - The server hashes it and stores only the hash.
- Later the user logs in and types a password.
- The server hashes what was typed and compares it with the stored hash.
- Equal hashes mean the same password was typed. The server still never knows the password itself.
This is also why a well built site cannot email you your old password. It can only let you set a new one. If a site emails your original password back to you, it is storing it in a recoverable form. That is a real warning sign about that site.
Why plain MD5 is wrong — three separate reasons
MD5 appears in almost every college mini-project. It is wrong for three different reasons, and students usually only know the first one.
Reason 1: MD5 is broken as a hash. Researchers can produce two different inputs with the same MD5 output in seconds on an ordinary laptop. That property, collision resistance, is gone. SHA-1 is in the same condition.
Reason 2: MD5 is fast, and speed helps the attacker. A modern GPU can compute billions of MD5 hashes per second. If someone steals your hash table, they simply hash every common password and compare. Speed is a feature for a checksum and a bug for a password.
Reason 3: identical passwords produce identical hashes. If two hundred users all chose password123, all two hundred rows look the same. An attacker who cracks one row has cracked all of them, and can also see at a glance which password is most popular in your database.
Switching MD5 to SHA-256 fixes reason 1 only. SHA-256 is still very fast and still deterministic. It is a fine hash for verifying a downloaded file. It is not a password hash.
Salt fixes reason 3
A salt is a random value, unique per user, stored next to the hash in plain sight. The server hashes the salt together with the password.
Two users with the same password now get different salts and therefore different stored values. Precomputed tables of common password hashes (rainbow tables) become useless, because the attacker would need a fresh table for every salt.
The salt does not need to be secret. It needs to be unique and random.
Slow hashes fix reason 2
The real answer is a password hashing function that is deliberately slow and memory-hungry, with a cost factor you can raise as hardware gets faster. The names to know:
- bcrypt — old, widely available, still acceptable.
- scrypt — adds a memory cost.
- Argon2id — the current recommendation, and the one to name in an interview.
These functions generate the salt for you and pack the algorithm, the cost factor and the salt into a single string that you store in one column. You do not need a separate salt column, and you never write the salt logic yourself.
A rough sense of the numbers: a properly configured Argon2id verification takes around a tenth of a second. That is invisible to one user logging in, and it turns a billion guesses per second into a few per second.
The rule you should remember
Use a maintained library. Never invent your own scheme, never chain hashes together hoping it helps, never write "SHA-256 twice" and call it secure. Password hashing is a solved problem, and the solution has a name.
Next: what happens after the password check passes.