How should you store user passwords in a database?
Tests knowledge of slow salted hashing versus encryption. Strong answers pick Argon2id or bcrypt, require unique per-user salts, describe verification via re-hashing with constant-time comparison, and cite bcrypt or argon2-cffi.
WHAT THIS TESTS: Whether you understand the difference between confidentiality and integrity in authentication storage. Interviewers want to see that you know passwords must survive database compromise without exposing usable credentials. The core concept is that hashing is one-way and intentionally slow, while encryption is reversible and fast hashing enables brute-force.
A GOOD ANSWER COVERS: Four things in order. First, algorithm choice: recommend Argon2id as the current OWASP preference, or bcrypt as a widely supported alternative, and explicitly reject fast algorithms like SHA-256 or MD5. Second, salting: explain that each password gets a unique random salt stored alongside the hash to defeat rainbow tables and precomputation. Third, verification flow: describe retrieving the salt for the user, feeding the submitted password and salt through the same algorithm with identical work factors, then comparing the resulting hash to the stored value using a constant-time comparison function to prevent timing attacks. Fourth, library selection: name bcrypt or argon2-cffi in Python, or note that Passlib wraps both, and mention that you never implement the algorithm yourself.
COMMON WRONG ANSWERS: Five red flags interviewers listen for. One, suggesting encryption or encoding like Base64, which implies the password can be recovered. Two, naming SHA-256 or other general-purpose fast hashes without mentioning thousands of iterations. Three, omitting salts or suggesting a global salt, which still allows batch attacks. Four, describing string comparison instead of constant-time comparison, leaking timing information. Five, saying you would write your own hashing routine rather than using a battle-tested library.
LIKELY FOLLOW-UPS: How do you upgrade the work factor over time without forcing every user to reset their password immediately. How you would handle password resets securely. What happens if a user picks a password that exceeds the 72-byte input limit of bcrypt. Whether peppering adds value and where the pepper should live.
ONE CONCRETE EXAMPLE: When a user registers, generate a 16-byte random salt. Hash the password with bcrypt using a cost factor of 12 or higher, producing a string that embeds the salt, cost, and hash. Store that entire string in the database. On login, retrieve the string, extract the cost and salt, hash the submitted password with those same parameters, and use a constant-time compare to check against the stored hash. In Python, bcrypt.checkpw handles both the hashing and comparison safely.
Read the original → cheatsheetseries.owasp.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.