Safeguard
Developer Tools•

bcrypt's 72 byte limit: truncation, pre-hashing and what to do

bcrypt ignores input past 72 bytes in most implementations. Why that matters, why naive pre-hashing is risky, and what OWASP suggests if you keep bcrypt.

Safeguard Security Team
3 min read

Most bcrypt implementations ignore everything past 72 bytes of input. Enforce a maximum password length of 72 bytes, or move to Argon2id. Pre-hashing long passwords is possible but easy to get wrong, because of null byte truncation and password shucking.

What the limit does

OWASP's password storage guidance says bcrypt has a 72 byte input limit in most implementations and recommends enforcing a 72 byte maximum password length for bcrypt. If a user sets a 100 byte passphrase, the last 28 bytes do nothing. Two different long passwords that share the first 72 bytes hash identically.

Bytes are not characters. A password in a script with multi-byte characters reaches 72 bytes in far fewer than 72 characters, so check bytes after encoding.

Why people reach for pre-hashing

To support long passphrases, some teams hash the password first, then feed the digest to bcrypt. The idea is sound, but the details bite.

  • Null bytes: a raw binary digest can contain a zero byte, and some bcrypt implementations stop reading at it. That silently shortens the effective input.
  • Password shucking: if you pre-hash with a plain fast hash, an attacker who holds a leaked database of those plain fast hashes from elsewhere can strip off the bcrypt layer and attack the cheap inner hash.

OWASP notes pre-hashing is risky for these reasons.

The safer pre-hash, if you must

OWASP's suggestion is to pre-hash with HMAC-SHA-384 keyed with a pepper, then base64 encode the result before passing it to bcrypt. The key defeats shucking, because the inner value is no longer reproducible from a public hash, and base64 avoids null bytes.

Notice what this requires: a pepper stored outside the database, handled like any secret. And per the OWASP text, replacing a compromised pepper means users reset passwords.

Easier options

  1. Switch new accounts to Argon2id, which OWASP prefers for new work (check your library for its own input limits), and rehash existing accounts at next login.
  2. If you stay on bcrypt, cap password length at 72 bytes, tell users, and reject longer input instead of truncating silently.
  3. Audit your library. Some wrappers truncate quietly, some raise an error, and a few have already added pre-hashing. Test with a 100 byte input to find out.

A short test

Write a unit test that hashes a password of 72 bytes plus a different suffix and confirms your code either rejects it or treats the two as different. A passing result for the wrong reason, such as both silently matching, is exactly the bug.

Quick check

Should I just truncate long passwords myself?

Silent truncation surprises users and weakens long passphrases. Rejecting input over the limit with a clear message is more honest.

Is bcrypt unsafe?

OWASP lists it for legacy systems with a work factor of at least 10, and prefers Argon2id for new work. It is acceptable with care, not a first choice.

Safeguard's dependency scanning can show which password hashing libraries and versions you ship, and the free scan at gold.safeguard.sh/scan is a quick place to start.

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.