Archivehashing
Salting and Peppering Password Hashes
A salt defeats precomputation; a pepper defeats a stolen database. Neither replaces a slow hash.
- Published
- Reading time
- 1 min read
A salt is a unique, public random value stored next to each hash. It makes precomputed rainbow tables useless and ensures two users with the same password get different digests. A pepper is a single secret value mixed in outside the database, so a SQL injection alone does not let an attacker verify guesses offline.
The mechanics
stored = argon2id(password, salt, pepper, params)
- Salt: 16 random bytes per user, stored in the row.
- Pepper: 32 random bytes, held in the application secret store, rotated with a version tag.
- Params: tuned to the hardware, not copied from a blog post.
Note that the pepper is not a substitute for a slow hash. If the application server is compromised, the pepper leaks with it. It only raises the bar for a database-only breach.
Common mistakes
- Reusing one global salt ("pepper" mislabeled) — loses per-user uniqueness.
- Storing the pepper in the same table — no added protection.
- Hashing with SHA-256 and calling it a day — GPU farms do billions per second.
Takeaway: salt for uniqueness, pepper for blast-radius reduction, and a memory-hard function for the actual work. All three or none.