To securely store passwords, we will use the bcrypt library, which is widely regarded for its strength and resistance to brute-force attacks. This tutorial will guide you through the installation of the library, how to hash passwords, and how to verify passwords against stored hashes.

Prerequisites

Before you begin, ensure you have Python installed on your machine. You can check your Python version by running:

python --version

You will also need to install the bcrypt library. You can do this using pip:

pip install bcrypt

Hashing Passwords

Hashing is a one-way cryptographic function that converts a password into a fixed-size string of characters, which is typically a hash. The bcrypt library provides a simple interface for hashing passwords.

Here’s how to hash a password:

import bcrypt

def hash_password(password: str) -> bytes:
    # Generate a salt
    salt = bcrypt.gensalt()
    # Hash the password
    hashed_password = bcrypt.hashpw(password.encode('utf-8'), salt)
    return hashed_password

# Example usage
password = "secure_password"
hashed = hash_password(password)
print(f"Hashed Password: {hashed}")

Verifying Passwords

When a user attempts to log in, you need to verify the provided password against the stored hash. Here’s how to do that:

def verify_password(stored_hash: bytes, password: str) -> bool:
    return bcrypt.checkpw(password.encode('utf-8'), stored_hash)

# Example usage
is_valid = verify_password(hashed, "secure_password")
print(f"Password is valid: {is_valid}")

Best Practices for Password Storage

When implementing password storage, consider the following best practices:

Best PracticeDescription
Use Strong Hashing AlgorithmsUse algorithms like bcrypt, Argon2, or PBKDF2 that are designed for password hashing.
Implement SaltingAlways use a unique salt for each password to prevent rainbow table attacks.
Use a Sufficient Work FactorAdjust the work factor of the hashing algorithm to increase computational cost.
Limit Login AttemptsImplement account lockout mechanisms to prevent brute-force attacks.
Store Hashes, Not Plain TextNever store passwords in plain text; always store the hashed version.
Regularly Update Hashing StrategiesStay informed about the latest security practices and update your hashing methods as necessary.

Example Application

Here’s a simple example of how you might implement secure password storage in a user registration and login system:

class User:
    def __init__(self, username: str, password: str):
        self.username = username
        self.password_hash = hash_password(password)

    def check_password(self, password: str) -> bool:
        return verify_password(self.password_hash, password)

# Simulating user registration
new_user = User("john_doe", "secure_password")

# Simulating user login
login_password = "secure_password"
if new_user.check_password(login_password):
    print("Login successful!")
else:
    print("Invalid password.")

Conclusion

Implementing secure password storage is essential for protecting user data and maintaining the integrity of your application. By using strong hashing algorithms like bcrypt, salting, and following best practices, you can significantly reduce the risk of password-related vulnerabilities.

Learn more with useful resources