Storing a password without regret
A slow hash with a salt, no pepper theatre, no cleverness, and a set of rules you should not deviate from without a very good reason.
General-purpose hashes are designed to be fast, which is exactly wrong here: fast means an attacker with your database can try billions of candidates. Password hashes are deliberately slow and memory-hard. Use argon2id if you can, bcrypt if that is what your stack gives you, tune the work factor so that a hash takes a few hundred milliseconds on your production hardware, and revisit it every couple of years. Never invent your own scheme, and never reach for SHA-256 with a salt because it sounds similar.
The salt is per-user and stored alongside the hash. That is normal and not a leak. Its job is to make precomputed tables useless and to ensure two users with the same password have different hashes. Modern libraries generate and embed it for you in the output string, along with the algorithm and parameters, which is what lets you upgrade the work factor gradually on login.
The reset flow is where accounts actually get taken. A single-use token with a short expiry, stored hashed so a database leak does not hand over live resets, invalidated on use and on password change. And the same response whether or not the email exists, because a reset form that says "no such user" is a free account-enumeration endpoint.
You should now be able to
- Explain why speed is the enemy in password hashing
- Choose and configure a modern password hash
- Design the reset flow without leaking who has an account
Loading…