Safeguard
Security Guides•

How do you upgrade password hashes without forcing a reset?

Raise your password hash cost without emailing every user. Re-hash at the next successful login. A step by step plan with OWASP minimum settings.

Safeguard Security Team
4 min read

Wait until each user next signs in, check the stored hash parameters, and if they are below your target, re-hash the password you just verified with the new settings and save it. OWASP calls this the most common approach. It upgrades active users with no reset emails and no downtime.

Why you cannot just recompute

You never stored the passwords, only hashes. A hash cannot be converted into a stronger hash of the same password. The only moment you hold the plaintext is during a successful login, so that is when the upgrade happens.

What the target settings are

OWASP's Password Storage Cheat Sheet gives these minimums.

AlgorithmMinimum setting from OWASPNote
Argon2id19 MiB memory, 2 iterations, 1 parallelismPreferred
scryptN of 2 to the 17 (128 MiB), r of 8, p of 1If Argon2id is unavailable
bcryptWork factor of at least 10Legacy systems, 72 byte limit
PBKDF2HMAC-SHA-256 with 600,000 iterationsWhen FIPS-140 compliance is needed

Treat these as floors and check the current page when you plan a change.

The login time upgrade, step by step

  1. Store the algorithm name and parameters with every hash. Most modern formats already embed them in the string.
  2. On login, verify the password against the stored hash as usual.
  3. If verification succeeds, compare the stored parameters with your current policy.
  4. If they are weaker, hash the plaintext with the new settings and overwrite the old value in the same transaction as the login.
  5. Log the upgrade as an event, without the password or hash.
  6. Track how many accounts remain on the old settings.

Many password libraries expose a function that tells you whether a hash needs rehashing, which saves you from writing the comparison yourself.

Changing algorithm, not just cost

Moving from a weak or fast hash to a proper one works the same way, with one trick. If the old values were plain fast hashes, you can wrap them right away without waiting for logins: feed the old hash into the new password hash and record that the row uses the wrapped scheme. On the next login, verify through the wrapped path, then store a clean new hash. This protects dormant accounts from the day you deploy.

What about accounts that never log in

Set a deadline. After it, expire the old hashes for inactive accounts and require a reset on their next visit. Decide this with support and security together, and tell users why.

Mistakes to avoid

  • Upgrading before the password is verified.
  • Writing the new hash in a separate request from the login, so a failure leaves a mix.
  • Keeping the old hash column around after the migration is done.
  • Silently capping password length at a value below what your new hash accepts.

Safeguard can generate an SBOM and scan your dependencies, so outdated cryptography libraries with known advisories show up in one inventory, and policies can gate a build on them. A free scan is at gold.safeguard.sh/scan.

Quick check

Do I need to tell users?

Not for a silent re-hash at login, since nothing changes for them. Do tell them if you require a reset.

Should I pick bcrypt or Argon2id for the new hash?

OWASP prefers Argon2id and lists bcrypt for legacy systems. If bcrypt is what you have, raise the work factor and plan a move.

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.