Skip to content
hashkey.bond

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.