Hasing passwords (bcrypt)

In this example:

  • hash_password() function hashes a password using a randomly generated salt.
  • verify_password() function verifies whether a provided password matches a hashed password.
  • derive_key() function derives a key from a password and salt using the bcrypt Key Derivation Function (KDF).
  • Example usage demonstrates hashing a password, verifying it, and deriving a key from a password and salt.
import bcrypt

# Function to hash a password
def hash_password(password):
    # Generate a salt
    salt = bcrypt.gensalt()
    # Hash the password with the generated salt
    hashed_password = bcrypt.hashpw(password.encode('utf-8'), salt)
    return hashed_password

# Function to verify a password
def verify_password(password, hashed_password):
    # Check if the provided password matches the hashed password
    return bcrypt.checkpw(password.encode('utf-8'), hashed_password)

# Function to derive a key from a password and salt
def derive_key(password, salt, desired_key_bytes, rounds):
    # Derive a key using bcrypt KDF
    derived_key = bcrypt.kdf(password.encode('utf-8'), salt, desired_key_bytes, rounds)
    return derived_key

# Example usage
if __name__ == "__main__":
    # Password to hash
    password = "my_secure_password"

    # Hash the password
    hashed_password = hash_password(password)
    print("Hashed Password:", hashed_password)

    # Verify the password
    is_valid = verify_password(password, hashed_password)
    print("Password Verified:", is_valid)

    # Derive a key
    salt = bcrypt.gensalt()
    derived_key = derive_key(password, salt, 32, 100000)
    print("Derived Key:", derived_key)
Code Explanation
  1. Importing the bcrypt Library:
import bcrypt
  • This line imports the bcrypt library, allowing us to use its functions for password hashing and key derivation.
  1. Defining Hashing Function:
def hash_password(password):
    salt = bcrypt.gensalt()
    hashed_password = bcrypt.hashpw(password.encode('utf-8'), salt)
    return hashed_password
  • This function hash_password() takes a password as input and returns its hashed version.
  • bcrypt.gensalt() generates a random salt, which is used to enhance the security of the password hashing process.
  • bcrypt.hashpw() hashes the provided password using the generated salt.
  • The password is encoded to bytes using UTF-8 encoding before hashing to ensure compatibility with bcrypt.
  1. Defining Verification Function:
def verify_password(password, hashed_password):
    return bcrypt.checkpw(password.encode('utf-8'), hashed_password)
  • This function verify_password() takes a password and its hashed version as input and returns True if the password matches the hashed password, otherwise False.
  • bcrypt.checkpw() checks if the provided password matches the hashed password using the bcrypt algorithm.
  • Again, the password is encoded to bytes using UTF-8 encoding before verification.
  1. Defining Key Derivation Function:
def derive_key(password, salt, desired_key_bytes, rounds):
    derived_key = bcrypt.kdf(password.encode('utf-8'), salt, desired_key_bytes, rounds)
    return derived_key
  • This function derive_key() derives a key from a password and salt using the bcrypt Key Derivation Function (KDF).
  • bcrypt.kdf() performs key derivation based on the provided password, salt, desired key length in bytes, and number of hashing rounds.
  • The derived key is returned as a bytes object.
  1. Example Usage:
if __name__ == "__main__":
    password = "my_secure_password"
    hashed_password = hash_password(password)
    print("Hashed Password:", hashed_password)
    is_valid = verify_password(password, hashed_password)
    print("Password Verified:", is_valid)
    salt = bcrypt.gensalt()
    derived_key = derive_key(password, salt, 32, 100000)
    print("Derived Key:", derived_key)
  • In the example usage block, we:
    • Define a sample password.
    • Hash the password using the hash_password() function and print the hashed password.
    • Verify the password using the verify_password() function and print the verification result.
    • Generate a random salt.
    • Derive a key from the password and salt using the derive_key() function with a desired key length of 32 bytes and 100,000 hashing rounds, then print the derived key.

This code demonstrates how to securely hash passwords, verify them, and derive cryptographic keys using the bcrypt library in Python. It emphasizes best practices for password handling and key management in applications.

Output

The output of the provided code would vary depending on the randomly generated salt and the specific hashing rounds used. However, I can illustrate the expected format of the output based on the code structure:

Hashed Password: b'$2b$12$2lEeWZjGVVhLMR1GKT3X7O4bUdpfZVLJh0jRw5QVj6kE4GsT3T3ZS'
Password Verified: True
Derived Key: b'?\x86\xd3\xe1\x06\x8c\x87W\xa8\xf3\xd2b\x97\x06\x8d9o\x87)\x8b0\xf7y\xc8\xa3\xd3\xb4Q\x94'