Safeguard
Security Guides•

Choosing a password hashing algorithm: Argon2id, scrypt, bcrypt, PBKDF2

Which password hashing algorithm to pick and with what settings, per OWASP: Argon2id first, then scrypt, bcrypt for legacy, PBKDF2 where FIPS is required.

Safeguard Security Team
3 min read

OWASP's order of preference is Argon2id first, then scrypt, then bcrypt for legacy systems, and PBKDF2 when FIPS-140 compliance is required. Whatever you pick, use a unique random salt per password and tune the cost to your hardware. Never store passwords with a plain, fast hash.

The recommended settings

From the OWASP Password Storage Cheat Sheet:

Argon2id (preferred). A minimum of 19 MiB of memory, 2 iterations and parallelism of 1. Equivalent trade offs include 46 MiB with 1 iteration, or 12 MiB with 3 iterations.

scrypt. When Argon2id is not available: cost parameter N of 2 to the power 17, block size 8 and parallelism 1. OWASP lists lower memory alternatives such as N of 2 to the power 16 with parallelism 2.

bcrypt. For legacy systems: a work factor of at least 10. Enforce a maximum password length of 72 bytes, or less if your library has a smaller limit.

PBKDF2. Where FIPS-140 is required: PBKDF2 with HMAC-SHA-256 at 600,000 iterations or more, or HMAC-SHA-512 at 220,000 or more.

These numbers are minimums at the time of the page. Benchmark on your own servers and recheck the current guidance when you set them.

Why slow and memory heavy

A password hash is meant to be expensive. If the database leaks, the attacker has to run the same expensive function for each guess. Memory heavy algorithms make large scale guessing on specialized hardware harder than purely CPU bound ones.

Salt and pepper

Each password needs a unique, randomly generated salt, which defeats precomputed tables and hides which users share a password. Most mainstream libraries create and store the salt for you.

A pepper is a secret value shared across stored hashes and kept somewhere else, such as a secrets vault or HSM, never next to the hash. OWASP calls it defense in depth that provides no protection on its own. Changing a pepper means affected users must reset their passwords.

The bcrypt trap

bcrypt only reads the first 72 bytes of input. Pre-hashing the password to get around this has its own problems. OWASP says that if you must pre-hash, use HMAC-SHA-384 keyed with a pepper and base64 encode the output. The simpler fix is to choose Argon2id for new systems.

Migrating old hashes

  1. Choose the new algorithm and settings.
  2. On each successful login, rehash the submitted password and store the new value.
  3. After a set period, force a reset for accounts that never logged in.
  4. Store an algorithm label with each hash so you can tell them apart.

What not to do

Do not use a fast general hash such as SHA-256 alone, do not invent your own scheme, and do not log passwords.

Safeguard's dependency scanning flags known issues in the crypto and authentication libraries your service uses. A free scan is at gold.safeguard.sh/scan.

Quick check

Is bcrypt still acceptable?

OWASP lists it for legacy systems with a work factor of at least 10 and a 72 byte password limit. For new systems it prefers Argon2id.

Do I need a pepper?

It is optional defense in depth. It only helps if stored apart from the database.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.