{"id":1008,"library":"passlib","title":"Passlib","description":"Passlib is a comprehensive password hashing framework for Python, supporting over 30 hashing schemes. The current stable version is 1.7.4, which is the last series to support Python 2.x. Future versions (Passlib 1.8+) will require Python 3.5 or newer. It provides cross-platform implementations and a robust framework for managing password hashes in applications.","status":"active","version":"1.7.4","language":"python","source_language":"en","source_url":"https://foss.heptapod.net/python-libs/passlib","tags":["security","hashing","passwords","cryptography","authentication"],"install":[{"cmd":"pip install passlib","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Optional: accelerates Bcrypt hashes. Users may need to pin version < 4.1.0 due to compatibility issues with passlib's internal handling.","package":"python-bcrypt","optional":true},{"reason":"Optional: accelerates PBKDF2-based hashes.","package":"python-fastpbkdf2","optional":true},{"reason":"Optional: accelerates SCrypt hashes.","package":"python-scrypt","optional":true}],"imports":[{"note":"Recommended for new applications to manage multiple schemes, deprecation, and upgrades.","symbol":"CryptContext","correct":"from passlib.context import CryptContext"},{"note":"For directly importing a specific hash algorithm, e.g., 'pbkdf2_sha256', 'bcrypt', 'argon2'.","symbol":"pbkdf2_sha256","correct":"from passlib.hash import pbkdf2_sha256"}],"quickstart":{"code":"from passlib.context import CryptContext\n\n# For new applications, it's recommended to use CryptContext\n# schemes=['bcrypt'] or schemes=['argon2'] are good modern choices.\n# 'deprecated=\"auto\"' ensures older hashes are automatically marked for upgrade.\npwd_context = CryptContext(\n    schemes=[\"pbkdf2_sha256\", \"bcrypt\"],\n    deprecated=\"auto\",\n    # Optionally, configure default rounds for schemes.\n    # Adjust these values based on current security recommendations and desired CPU cost.\n    pbkdf2_sha256__rounds=600000,\n    bcrypt__rounds=12,\n)\n\npassword = \"supersecretpassword\"\n\n# Hash the password\nhashed_password = pwd_context.hash(password)\nprint(f\"Hashed password: {hashed_password}\")\n\n# Verify the password\nis_valid = pwd_context.verify(password, hashed_password)\nprint(f\"Password valid: {is_valid}\")\n\n# Verify with wrong password\nis_invalid = pwd_context.verify(\"wrongpassword\", hashed_password)\nprint(f\"Wrong password valid: {is_invalid}\")\n\n# Check if hash needs to be upgraded (e.g., if a deprecated scheme was used or rounds are too low)\nneeds_upgrade = pwd_context.needs_update(hashed_password)\nprint(f\"Hash needs upgrade: {needs_upgrade}\")\n\nif needs_upgrade:\n    print(\"Upgrading hash...\")\n    new_hashed_password = pwd_context.hash(password)\n    print(f\"New Hashed password after upgrade: {new_hashed_password}\")","lang":"python","description":"This quickstart demonstrates how to use `CryptContext` to hash and verify passwords. `CryptContext` provides a flexible way to manage various hashing schemes, including automatic deprecation and upgrade detection, which is crucial for long-term password security. Modern schemes like `pbkdf2_sha256`, `bcrypt`, and `argon2` are recommended."},"warnings":[{"fix":"Ensure your project uses Python 3.5+ before upgrading to Passlib 1.8. Consider migrating Python 2.x code if still in use.","message":"Passlib 1.7.x is the last series to support Python 2.x, 3.3, and 3.4. Passlib 1.8 and later will require Python >= 3.5.","severity":"breaking","affected_versions":"1.8+"},{"fix":"Monitor Passlib's official channels for updates regarding Python 3.13 compatibility. Consider alternatives like `pwdlib` if issues arise or maintenance remains stalled.","message":"The `crypt` module will be removed in Python 3.13. While Passlib 1.7.4 includes fallbacks, there are concerns about its long-term maintenance and full compatibility with Python 3.13 without active updates to address this.","severity":"breaking","affected_versions":"1.7.4 (potential issues with Python 3.13)"},{"fix":"Downgrade the `bcrypt` package to version `4.0.1` or lower (`pip install bcrypt==4.0.1`) if you rely on Passlib's `bcrypt` scheme.","message":"Passlib has known compatibility issues with `bcrypt` versions 4.1.0 and above. When using the `bcrypt` scheme, Passlib may encounter an `AttributeError` due to changes in the `bcrypt` module.","severity":"gotcha","affected_versions":"1.7.4 with bcrypt >= 4.1.0"},{"fix":"Always use the `.verify()` method provided by `Passlib` (e.g., `pwd_context.verify(password, hashed_hash)`) which uses constant-time comparison.","message":"Direct string comparison (e.g., `hashed_password == other_hash`) to verify passwords is insecure and vulnerable to timing attacks.","severity":"gotcha","affected_versions":"All"},{"fix":"Understand that different hash outputs for the same password are a security feature, not a bug. Store only one hash per password and use `.verify()` for checks.","message":"Calling `PasswordHash.hash()` or `CryptContext.hash()` multiple times with the same plaintext password will produce different hash strings each time (for salted schemes). This is expected behavior as a new random salt is generated with each call.","severity":"gotcha","affected_versions":"All"}],"env_vars":null,"last_verified":"2026-05-12T22:32:08.006Z","next_check":"2026-06-27T00:00:00.000Z","problems":[{"fix":"Ensure 'passlib' is installed in your active Python environment using pip: `pip install passlib` or `pip3 install passlib`. If using a virtual environment, activate it before installing.","cause":"The 'passlib' library is not installed in the Python environment being used, or the Python interpreter cannot find it due to environment path issues or virtual environment misconfiguration.","error":"ModuleNotFoundError: No module named 'passlib'"},{"fix":"Encode the password string to bytes (e.g., UTF-8) before passing it to the hashing function: `password.encode('utf-8')`.","cause":"This error occurs when attempting to hash a Python Unicode string directly with 'passlib' (or its underlying hashing backends like bcrypt) without first encoding it into bytes.","error":"TypeError: Unicode-objects must be encoded before hashing"},{"fix":"Either ensure passwords do not exceed 72 bytes (e.g., `password[:72]`) or, if the issue is a `bcrypt` version conflict, pin `bcrypt` to an earlier compatible version like 4.3.0 in your `requirements.txt`: `bcrypt==4.3.0`.","cause":"The bcrypt hashing algorithm, often used via 'passlib', has a hard limit of 72 bytes for passwords. This error indicates the provided password exceeds this length. This can also be caused by compatibility issues with newer `bcrypt` versions (e.g., 5.0.0) where internal behavior changes caused problems even with shorter inputs.","error":"ValueError: password cannot be longer than 72 bytes"},{"fix":"Downgrade the 'bcrypt' library to a version compatible with 'passlib' 1.7.4, for example: `pip install \"bcrypt==4.0.1\"` or `pip install \"bcrypt<4.1.0\"`.","cause":"This error typically arises from an incompatibility between the installed 'passlib' version and a newer version of the 'bcrypt' backend library, where 'bcrypt' removed the `__about__` attribute that 'passlib' was attempting to access.","error":"AttributeError: module 'bcrypt' has no attribute 'about'"},{"fix":"Ensure the hash string passed to methods like `hash.verify()` or `hash.identify()` is a valid, correctly formatted hash previously generated by `passlib` or a compatible system.","cause":"This error occurs when `passlib` tries to parse or verify a string that does not conform to a valid hash format for the expected scheme.","error":"ValueError: Not a valid password hash"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":null,"quickstart_tag":null,"pypi_latest":"1.7.4","cli_name":"","install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.07,"mem_mb":2.7,"disk_size":"21.3M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.07,"mem_mb":2.7,"disk_size":"21.3M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.6,"import_time_s":0.05,"mem_mb":2.7,"disk_size":"22M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.05,"mem_mb":2.7,"disk_size":"22M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.12,"mem_mb":3.1,"disk_size":"23.9M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.13,"mem_mb":3.1,"disk_size":"23.9M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.7,"import_time_s":0.1,"mem_mb":3.1,"disk_size":"24M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.1,"mem_mb":3.1,"disk_size":"24M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.1,"mem_mb":3,"disk_size":"15.6M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.12,"mem_mb":3,"disk_size":"15.6M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.6,"import_time_s":0.1,"mem_mb":3,"disk_size":"16M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.11,"mem_mb":3,"disk_size":"16M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.09,"mem_mb":3.6,"disk_size":"15.3M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.1,"mem_mb":3.2,"disk_size":"15.2M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.7,"import_time_s":0.1,"mem_mb":3.5,"disk_size":"16M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.09,"mem_mb":3,"disk_size":"16M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.06,"mem_mb":2.6,"disk_size":"20.8M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.07,"mem_mb":2.6,"disk_size":"20.8M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.9,"import_time_s":0.06,"mem_mb":2.6,"disk_size":"21M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.07,"mem_mb":2.6,"disk_size":"21M"}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":null,"tag_description":null,"results":[{"runtime":"python:3.10-alpine","exit_code":0},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":0},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":0},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":0},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":0},{"runtime":"python:3.9-slim","exit_code":0}]}}