Bcrypt 72-Byte Password Length Limit

Understand bcrypt's 72-byte password length limit, why it exists, and practical workarounds. Learn the pre-hashing technique used by Django and Dropbox to handle passwords longer than 72 bytes safely.

Best Practices

Detailed Explanation

Bcrypt 72-Byte Password Length Limit

Bcrypt has a hard limit of 72 bytes for the input password. Any characters beyond byte 72 are silently ignored during hashing and verification. This is a consequence of the Blowfish cipher’s key schedule, which accepts keys up to 72 bytes.

Why 72 Bytes?

Blowfish accepts keys between 4 and 56 bytes. Bcrypt’s Eksblowfish variant extends this to 72 bytes (56 bytes of key + 16 bytes of salt combined in the key schedule). The 72-byte limit is a fundamental constraint of the algorithm, not an implementation choice.

How Many Characters Is 72 Bytes?

It depends on the encoding:

  • ASCII characters (a–z, 0–9): 72 characters = 72 bytes
  • UTF-8 multibyte (e.g., CJK characters): as few as 18–24 characters
  • Emoji: as few as 18 characters (most emoji are 4 bytes in UTF-8)

The Practical Risk

For most users, 72 bytes is not a real limitation — few people type passwords longer than 72 ASCII characters. However, the risk arises with:

  • Generated passphrases — "correct horse battery staple" style phrases can exceed 72 bytes
  • Password managers — may generate 128-character random passwords
  • API keys or tokens — often longer than 72 bytes

Two passwords that share the same first 72 bytes but differ afterward will produce the same bcrypt hash, which is a security issue.

The Pre-Hashing Workaround

The standard solution is to hash the password with SHA-256 (or SHA-512) before passing it to bcrypt:

import bcrypt
import hashlib
import base64

def bcrypt_sha256(password: str) -> str:
    # SHA-256 produces a fixed 32-byte hash (64 hex chars)
    sha_hash = hashlib.sha256(password.encode('utf-8')).digest()
    # Base64-encode to get a safe ASCII string (44 chars, well under 72)
    b64_hash = base64.b64encode(sha_hash)
    return bcrypt.hashpw(b64_hash, bcrypt.gensalt(12)).decode()

This technique is used by:

  • DjangoBCryptSHA256PasswordHasher
  • Dropbox — their published password hashing scheme

Important: Base64-Encode the Pre-Hash

If you pass raw SHA-256 bytes to bcrypt, null bytes in the hash will cause truncation in some implementations. Always Base64-encode or hex-encode the intermediate hash before feeding it to bcrypt.

Alternatives Without the Limit

If the 72-byte limit is a concern, consider:

  • Argon2 — no practical password length limit
  • scrypt — no practical password length limit
  • PBKDF2-SHA-256 — no practical password length limit

Should You Worry?

For most web applications where passwords are under 50 characters, the 72-byte limit has no practical impact. If you accept long passphrases, API keys, or non-ASCII passwords, implement pre-hashing as a precaution.

Use Case

The 72-byte limit becomes relevant when designing password policies for applications that encourage long passphrases, when hashing API keys or tokens, or when supporting international users whose characters may consume multiple bytes in UTF-8. Development teams building security-critical applications should implement pre-hashing proactively rather than discovering the truncation issue after deployment.

Try It — Bcrypt Generator

Open full tool