gotchapythonfastapiMajor
passlib + bcrypt 4.1+ incompatibility — use bcrypt directly
Viewed 0 times
passlib 1.7.4, bcrypt 5.0.0, Python 3.11
passlib CryptContextbcrypt ValueErrorpassword hashing incompatibility
docker
Error Messages
Problem
passlib 1.7.4 is incompatible with bcrypt >= 4.1. When using passlib's CryptContext with bcrypt scheme, hashing a password raises ValueError: "password cannot be longer than 72 bytes, truncate manually if necessary". This happens because passlib's internal detection logic for bcrypt wrap bugs calls verify with a test string that triggers the new bcrypt library's strict length check.
Solution
Use the bcrypt library directly instead of passlib's CryptContext. bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt()) for hashing and bcrypt.checkpw(plain.encode("utf-8"), hashed.encode("utf-8")) for verification. This avoids passlib entirely and works with bcrypt 4.x and 5.x. Alternative: pin bcrypt<4.1 in requirements, but that is a temporary workaround.
Why
passlib 1.7.4 has not been updated since 2020 and its internal bcrypt backend detection code calls bcrypt's verify with test strings in a way that triggers bcrypt 4.1+'s new strict validation. The passlib project appears unmaintained.
Gotchas
- passlib is unmaintained — do not rely on it for new projects
- bcrypt 4.1+ enforces strict 72-byte password limit that passlib's internal tests trigger
- If you must use passlib, pin bcrypt<4.1 but this is a temporary fix
Code Snippets
Direct bcrypt usage for password hashing (works with bcrypt 4.x/5.x)
import bcrypt
def hash_password(password: str) -> str:
return bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt()).decode("utf-8")
def verify_password(plain: str, hashed: str) -> bool:
return bcrypt.checkpw(plain.encode("utf-8"), hashed.encode("utf-8"))Context
Adding email/password authentication to a FastAPI backend that already has bcrypt installed (version 4.1+) and passlib[bcrypt] in dependencies.
Revisions (0)
No revisions yet.