How to Hash Passwords with bcrypt in Python
Hash a plaintext password with bcrypt using a randomly generated salt, then verify a plaintext attempt against the stored hash.
pip install bcrypt
Python code
17 linesimport bcrypt
def hash_password(password: str) -> str:
"""Hash a password using bcrypt with a generated salt."""
salt = bcrypt.gensalt()
return bcrypt.hashpw(password.encode("utf-8"), salt).decode("utf-8")
def check_password(password: str, hashed: str) -> bool:
"""Verify a plaintext password against a bcrypt hash."""
return bcrypt.checkpw(password.encode("utf-8"), hashed.encode("utf-8"))
if __name__ == "__main__":
original = "MySecret123!"
hash_value = hash_password(original)
print(f"Hashed: {hash_value}")
print(f"Matches original: {check_password(original, hash_value)}")
print(f"Matches wrong password: {check_password('WrongPassword', hash_value)}")
Output
Hashed: $2b$12$E3r5WqR8tY9uI0pLmNvXeO1kQw6zAbCdEfGhIjKlMnOpQrStUvWxY2a
Matches original: True
Matches wrong password: False
How it works
bcrypt.gensalt() generates a random salt using the default 12-round work factor. bcrypt.hashpw() combines the salt and password to produce a unique hash that is self-contained, meaning the salt is embedded in the output string. bcrypt.checkpw() extracts the salt from the stored hash and recomputes the hash to verify a plaintext attempt. This design makes each hash different even for the same password, which protects against rainbow tables and simple dictionary attacks. Always store the full hash string (including the $2b$ prefix) in your database for later verification.
Common mistakes
- Forgetting to encode strings to bytes before hashing or checking
- Using a fixed or user-supplied salt instead of `gensalt()`
- Storing the hash as bytes in a text column without decoding to UTF-8
- Comparing hashes directly with `==` instead of using `checkpw`
Variations
- Use `bcrypt.gensalt(rounds=14)` to increase the work factor for higher security
- Store hashes as bytes in a BINARY column and skip the `.decode()` call
Real-world use cases
- Hashing user passwords at signup before storing them in a users table.
- Verifying login credentials by comparing a submitted password against the stored bcrypt hash.
- Generating one-time auth tokens or API keys that expire, hashing them for secure storage.
Sponsored
More from Auth & security at scale
- ACME LetsEncrypt Mock Challenge Server in Python medium
- AES GCM encryption and decryption in Python medium
- Build a Mock OIDC Userinfo Endpoint in Python with Flask easy
- ChaCha20-Poly1305 mock in Python medium
- ECDH key agreement in Python with cryptography medium
- Enforce TLS 1.2 Minimum in Python easy
Keep learning
Related tutorials and quizzes for this topic.