Python’s bcrypt
library is a highly secure way of handling password hashing and verification. It’s a wrapper around the OpenBSD bcrypt
implementation, designed specifically to hash passwords in a secure way. The bcrypt hashing algorithm is resistant to rainbow table and brute force attacks because of its adaptive nature, meaning it becomes slower as computational power increases.
bcrypt
?bcrypt
To start using bcrypt
, you’ll need to install the library. You can do this via pip:
pip install bcrypt
The primary use case for bcrypt
is hashing passwords securely. Here’s an example:
import bcrypt
password = b"my_super_secure_password"
hashed_password = bcrypt.hashpw(password, bcrypt.gensalt())
print(f"Hashed Password: {hashed_password.decode()}")
b
prefix).hashpw
hashes the password using a salt generated by gensalt
.To authenticate a user, you can verify the provided password against the stored hash:
def verify_password(stored_hash, password):
return bcrypt.checkpw(password.encode(), stored_hash)
# Example usage
hashed = bcrypt.hashpw(b"example_password", bcrypt.gensalt())
print(verify_password(hashed, "example_password")) # Output: True
print(verify_password(hashed, "wrong_password")) # Output: False
True
if the password matches the hash, otherwise False
.The gensalt
function accepts a cost parameter that controls the complexity of the hash. The higher the cost, the more computationally expensive it is to generate and verify the hash.
# Using a higher cost for more computational complexity
high_cost_salt = bcrypt.gensalt(rounds=14)
high_cost_hash = bcrypt.hashpw(b"high_cost_password", high_cost_salt)
print(f"High Cost Hash: {high_cost_hash.decode()}")
On some systems, it may be desirable to use a cryptographic random number generator specific to the environment. Python’s bcrypt
allows you to pass in a custom function for random number generation:
import os
# Custom function to generate cryptographic random bytes
def custom_random(size):
return os.urandom(size)
# Generate a custom salt using the custom random function
custom_salt = bcrypt.gensalt(12, custom_random)
custom_hash = bcrypt.hashpw(b"custom_random_password", custom_salt)
print(f"Custom Random Hash: {custom_hash.decode()}")
os.urandom
.The bcrypt
library also provides some utility functions to work with hashes directly.
The bcrypt
library doesn’t offer a direct way to parse hashes, but its structure is standardized as $2b$cost$salt$hash
. Here’s an example of parsing:
import re
hash_pattern = r'\$2[abxy]\$(\d{2})\$(.{22})(.+)'
hashed = bcrypt.hashpw(b"my_password", bcrypt.gensalt())
# Extract the components using regex
match = re.match(hash_pattern, hashed.decode())
if match:
cost, salt, hash_value = match.groups()
print(f"Cost: {cost}, Salt: {salt}, Hash: {hash_value}")