libpass: Comprehensive Password Hashing Framework
libpass is an actively maintained fork of the original `passlib` library, providing a comprehensive password hashing framework that supports over 30 schemes. It is currently at version 1.9.3 and receives regular updates to address compatibility issues, security concerns, and support newer Python versions.
Common errors
-
ModuleNotFoundError: No module named 'passlib'
cause The `libpass` package is not installed in the currently active Python environment, or the virtual environment is not correctly activated.fixEnsure `libpass` is installed via `pip install libpass`. Verify your virtual environment is activated, or that the correct Python interpreter is being used. -
ValueError: password cannot be longer than 72 bytes, truncate manually if necessary
cause You are using `bcrypt` version 5.0.0 or higher with a password exceeding 72 bytes. `bcrypt` 5.0.0 changed its behavior to raise an error for overly long passwords, instead of silently truncating them.fixUpgrade `libpass` to version 1.9.3 or newer, as it includes compatibility fixes for `bcrypt` 5.0.0+. Alternatively, ensure that any passwords passed to `bcrypt` are 72 bytes or shorter, or pin `bcrypt<5.0.0` in your `requirements.txt`. -
ImportError: cannot import name 'CryptContext' from 'libpass.context'
cause You are attempting to import from `libpass.context` instead of `passlib.context`. `libpass` maintains the original `passlib` import paths for compatibility.fixChange your import statement to `from passlib.context import CryptContext`.
Warnings
- breaking The `bcrypt` library (a common optional dependency) introduced a breaking change in version 5.0.0. Passwords longer than 72 bytes now raise a `ValueError` instead of being silently truncated. This can cause applications to fail if not handled.
- breaking Python 3.13 removed the built-in `crypt` module, which older versions of `passlib` (and thus `libpass`) sometimes relied upon as a fallback. Running older `libpass` versions on Python 3.13+ can lead to `ModuleNotFoundError` or similar issues for certain hashing schemes.
- gotcha Installing both the original `passlib` package and `libpass` concurrently can lead to unexpected behavior and import conflicts, as `libpass` is designed as a direct drop-in replacement.
- gotcha While the package is installed as `libpass`, all imports within your code should use `passlib` (e.g., `from passlib.context import CryptContext`). Attempting to import from `libpass` directly will result in an `ImportError` for this specific fork.
Install
-
pip install libpass
Imports
- CryptContext
from libpass.context import CryptContext
from passlib.context import CryptContext
- pbkdf2_sha256
from passlib.hash import pbkdf2_sha256
Quickstart
from passlib.context import CryptContext
# Configure a context with desired hashing schemes
# Common schemes include 'sha512_crypt', 'bcrypt', 'pbkdf2_sha256', 'argon2'
context = CryptContext(
schemes=["sha512_crypt", "bcrypt", "pbkdf2_sha256", "argon2"],
# For real applications, configure rounds/iterations for security and performance
sha512_crypt__rounds=656000,
bcrypt__rounds=12,
pbkdf2_sha256__rounds=150000
)
password = "supersecretpassword"
# Hash a password
hashed_password = context.hash(password)
print(f"Hashed password: {hashed_password}")
# Verify a password against a hash
is_valid = context.verify(password, hashed_password)
print(f"Password valid: {is_valid}")
# Example with a wrong password
is_invalid = context.verify("wrongpassword", hashed_password)
print(f"Wrong password valid: {is_invalid}")