security authentication ai_generated true

Bcrypt accepts password but silently ignores characters beyond 72 bytes

ID: security/bcrypt-silent-truncation-72-bytes

Also available as: JSON · Markdown
88%Fix Rate
90%Confidence
3Evidence
2023-01-01First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
any active

Root Cause

Bcrypt has a hard 72-byte input limit (not characters - bytes). UTF-8 passwords with multibyte characters hit this limit sooner. Two passwords that share the first 72 bytes but differ after are treated as identical.

generic

Workarounds

  1. 92% success Pre-hash password with SHA-256 before bcrypt to handle arbitrary lengths
    import hashlib; prehashed = hashlib.sha256(password.encode()).hexdigest(); bcrypt.hashpw(prehashed.encode(), salt)
  2. 90% success Use SHA-256 pre-hash and encode as base64 to stay within 72 bytes
    prehash = base64.b64encode(hashlib.sha256(password.encode()).digest())  # always 44 bytes
  3. 88% success Consider Argon2id which has no practical input length limit
    from argon2 import PasswordHasher; ph = PasswordHasher(); hash = ph.hash(password)  # no truncation

Dead Ends

Common approaches that don't work:

  1. Use bcrypt for passwords of any length without pre-processing 90% fail

    Passwords longer than 72 bytes are silently truncated. 'MySecurePassword123!+extra100characters' and 'MySecurePassword123!+extra100different' hash identically.

  2. Set a maximum password length of 72 characters 82% fail

    72 bytes != 72 characters for UTF-8. A password with CJK characters or emojis uses 3-4 bytes per character, hitting the 72-byte limit at 18-24 characters.