Question presented to candidate: "A teammate suggests encrypting passwords with AES before storing them in the database, so they can be decrypted later if needed. What is wrong with that approach, and what should be done instead?"
What a strong answer should cover:
- Passwords should never be stored in plain text, and — the specific mistake in the prompt — should never be stored encrypted (reversibly) either. A password should be hashed with a purpose-built, one-way, slow algorithm: the application should never be able to recover the original password, only verify a guess against the stored hash.
- 📌 Salting is mandatory, not optional: a random, unique salt per password ensures that two users with the identical password produce completely different stored hashes — defending against precomputed rainbow-table attacks and revealing nothing about password reuse across accounts, verifiably, not just in theory.
- The hashing algorithm must be deliberately slow and memory-hard — general-purpose fast hashes (MD5, SHA-256 used alone) are the wrong tool specifically because they are fast, which makes brute-forcing millions of guesses per second on stolen hashes cheap. Purpose-built choices: bcrypt, scrypt (available in Node's built-in
cryptomodule, no external package needed), or Argon2 (the current, widely recommended default for new systems). - Comparing a supplied password's hash against the stored hash should use a constant-time comparison (
crypto.timingSafeEqual), not a naive===/Buffer.compare, to avoid leaking timing information about how many leading bytes matched. - A precise answer separates hashing algorithm choice from application-level concerns that matter just as much in practice: rate-limiting login attempts, never logging raw passwords, and using HTTPS so the password is not exposed in transit before it ever reaches the hashing step.
crypto.scrypt/scryptSyncare genuinely built into Node with no external dependency required, which is worth naming precisely — many engineers assume secure password hashing always requires installingbcrypt.
Clarifying questions expected:
- "Is this for a new system, or auditing an existing one that might already use a weak algorithm?" — decides between "pick a good algorithm" and "plan a migration."
- "Does the interviewer want the hashing mechanism specifically, or the broader set of related practices (rate limiting, transport security)?"
Code / implementation expected: Yes — a real, working hash-and-verify pair (using Node's built-in crypto.scrypt, demonstrating both the salting property and constant-time comparison) is the concrete, convincing deliverable here.