Salt & Pepper (Cryptography)
Random data added to a password before it is hashed to protect against rainbow table and brute-force attacks.
Detailed Explanation
A 'Salt' is a unique random string stored alongside the hashed password in the database; it ensures that two users with the same password have different hashes. A 'Pepper' is similar but is stored in the application code or a separate secure vault, not the database. This provides an extra layer of security if the database itself is compromised.
Quick Summary
A salt is per-password random data stored next to the hash; a pepper is a secret kept outside the database. Together they defeat rainbow tables and limit damage from a leaked password store.
Key Takeaways
- Salts must be unique per password and at least 16 bytes from a cryptographic RNG, never reuse, never derive from username.
- Salts are NOT secret; storing them next to the hash is fine and required for verification.
- Peppers ARE secret; if leaked along with the database, they provide no extra protection, keep them in a separate vault or KMS.
- Modern password hashers (bcrypt, argon2, scrypt) handle salting automatically, don't roll your own.
- Without a salt, identical passwords produce identical hashes, and precomputed rainbow tables crack them instantly.
When to use it
- Hardening a credential database so a leak doesn't immediately reveal user passwords.
- Adding a pepper as defense-in-depth when database backups are stored in less-trusted locations.
- Migrating legacy unsalted (MD5/SHA-1) password stores to bcrypt or argon2.
Common Mistakes
- Using a single global salt, equivalent to no salt for rainbow-table purposes.
- Storing the pepper in the same database or environment file as the hashes.
- Implementing custom hash-then-salt code instead of using a vetted library, easy to get the ordering or encoding wrong.
Salt & Pepper (Cryptography), Frequently Asked
Do I need a pepper if I'm already using bcrypt?
It's optional. Bcrypt with a strong work factor is already enough for most apps. A pepper adds value only if you can keep it strictly outside the database boundary (HSM, separate KMS), otherwise it's theater.
Where should the salt live?
Encoded inside the same string as the hash. Bcrypt and argon2 output formats include the salt by design (`$2b$12$<salt><hash>`), so you just store one field and the library handles the split on verify.