Security

What Is a Pepper in Password Hashing?

Dr. Anika Rhodesยทยท9 min read

A stolen password table is bad. A stolen password table that is still missing one essential secret is materially less bad. That is the narrow, useful promise of a password pepper: it separates one ingredient from the hashes so a database-only breach does not immediately become an offline guessing contest.

The name makes pepper sound like salt with extra attitude. It is not. Salt and pepper have different storage rules, different jobs, and very different failure modes. Understanding those differences is what turns peppering from crypto garnish into a real layer of defense.

What is a password pepper?

A password pepper is a secret value incorporated into password hashing but kept outside the password database. The application retrieves it from a secrets manager or hardware security module when it needs to hash or verify a password. An attacker who copies only the users table gets the hashes and salts, but not the pepper needed to reproduce them.

Think of a bank deposit box that needs two things: the customer's key and the bank's key. The database contains one side of the evidence; the application owns the other. Copying the box does not copy the bank's key.

That protection has a strict boundary. If an attacker compromises both the database and the running application or its secret store, the pepper is available too. Peppering reduces the blast radius of one common breach path; it does not make a fully compromised system safe.

Pepper vs salt

A password salt is random, unique for each password, and public. Bcrypt stores its salt directly inside the resulting hash string. The salt ensures that two users who choose the same password still get different hashes and that an attacker cannot reuse one precomputed lookup table across the database.

A pepper is secret, stored away from the hashes, and usually shared across many records. Its job is separation: a database dump alone is incomplete. The clean comparison is:

Property Salt Pepper
Secret? No Yes
Unique per password? Yes Usually no
Stored with the hash? Yes No
Main defense Precomputation and identical hashes Database-only breach
Required? Yes Optional defense in depth

You do not choose between them. A sound design uses a unique salt every time and may add a pepper when the extra operational complexity is justified.

How peppering works

There are two common designs. In pre-hash peppering, the server combines the password with a secret before passing the result into Argon2id, scrypt, or bcrypt. In post-hash peppering, the server first creates the ordinary salted password hash and then authenticates that result with an HMAC, using the pepper as the HMAC key.

Post-hash HMAC has a helpful separation of responsibilities: the password-hashing library handles salts and work factors, while a standard keyed operation supplies the secret layer. Pre-hashing needs more care, particularly around input encoding and bcrypt's 72-byte input limit. Either pattern should come from a reviewed design and established libraries, not a home-built concatenation convention.

You can use the bcrypt generator to see that a proper password hash already includes a random salt and cost parameter, then verify the encoded result with bcrypt compare. Those browser tools illustrate bcrypt itself; production peppering must remain server-side because sending the secret to a browser would stop it being secret.

What a pepper protects against

Suppose an SQL injection flaw exposes the users table or an old database backup leaks. Without a pepper, an attacker has everything required for offline guessing: each stored hash, its salt, the algorithm, and its cost settings. The guesses may be expensive, but the attacker can run them privately for as long as needed.

With a properly separated pepper, that dump is missing an input. The attacker must also compromise the application environment, vault, or HSM before password guesses can be checked. This is why the OWASP password-storage guidance describes peppering as defense in depth and recommends keeping the secret in a vault or HSM rather than beside the hashes.

Pepper does not rescue weak foundations. Fast SHA-256 hashes remain fast; reused salts remain reused; password123 remains guessable. Start with a deliberately expensive password hash โ€” Argon2id, scrypt, or bcrypt โ€” and strong inputs from a password generator. Add pepper only after those basics are correct.

The rotation problem

The hardest part of peppering is not choosing a random secret. It is changing one. A server cannot generally take an existing one-way password hash and convert it to a new pre-hash pepper without seeing the user's password again.

A planned rotation can keep an old and new pepper version temporarily. When a user logs in, verify with the old version, then hash the submitted password under the new version and update the record. Dormant accounts never pass through that migration, so after a suspected pepper compromise the safe response may be to invalidate credentials and require password resets.

This tradeoff deserves a runbook before launch: identify who can access the pepper, how access is audited, how versions are recorded, what happens when the vault is unavailable, and how users are migrated after rotation. A secret nobody can rotate safely is future incident debt.

A practical password storage stack

Use a layered order that gives each control one job:

  1. Start with a strong, unique password; length and randomness set the resistance before hashing.
  2. Hash with Argon2id, scrypt, or bcrypt using a fresh salt generated by the library.
  3. Tune the work factor on production hardware so verification is deliberately costly but operationally sustainable.
  4. If your threat model warrants it, add a pepper stored in an independently protected secret system.
  5. Rate-limit online login attempts and protect recovery flows, because password hashing primarily addresses offline attacks.

The first three steps are the foundation. Pepper is step four on purpose.

The takeaway

A password pepper is a separate secret that makes a stolen database insufficient on its own. It complements a public per-password salt and an expensive password hash; it replaces neither. Keep it out of source control and out of the password database, plan rotation before you need it, and treat it as a carefully managed extra barrier rather than magic seasoning.

Try the tools

Frequently Asked Questions

What is a pepper in password hashing?

A pepper is a secret value combined with passwords as an extra layer around password hashing. Unlike a salt, it is not stored in the password database. It belongs in a secrets manager, vault, or hardware security module, so an attacker who steals only the database still lacks something required to test guesses.

What is the difference between a salt and a pepper?

A salt is a different random value for every password and is stored openly beside or inside the hash. A pepper is secret, stored separately, and is commonly shared by many password records. Salt prevents reusable precomputed attacks and matching hashes; pepper protects against a database-only compromise.

Should every user have a different pepper?

Usually no. A system commonly keeps one application pepper, or a small set of versioned peppers, in a protected secret store. A unique secret per user creates a difficult key-management problem without replacing the need for a unique per-password salt.

Where should a password pepper be stored?

Store it outside the database that contains password hashes, preferably in a managed secrets vault or HSM with tightly limited access and audit logging. Putting it in the same database, source code, container image, or committed environment file defeats the separation a pepper is meant to provide.

Can a password pepper be rotated?

Yes, but not by simply re-hashing stored hashes with a new pre-hash pepper. The server normally needs the user's plaintext password, so a practical migration verifies with the old pepper at login and immediately re-hashes with the new one. If the pepper is compromised, forced password resets may be necessary.

DA

Dr. Anika Rhodes writes for CodeUtilityKit, where the team builds free, privacy-first developer tools that run entirely in your browser. Every guide is written and reviewed by developers who use these tools daily.