Location>code7788 >text

Hashing and validating system user passwords with bcrypt or Passlib in Python development

Popularity:316 ℃/2024-08-21 11:35:16

In the design of a system, there will certainly be user authentication issues, the general verification of the user, are the user exists in the database to determine the total password hash value, so as to avoid password leakage and reverse decryption, then in the Python development, we can introduce bcrypt or Passlib on the system to the user password hash and verify the processing, as well as the introduction of using the other libraries to realize regular encryption and decryption processing operations. This essay mainly introduces the differences between bcrypt and Passlib, as well as some code for reference in actual use.

1、bcrypt cap (a poem)Introduction to Passlib

bcrypt cap (a poem)Passlib are both Python libraries for password hashing and authentication, but they have some significant differences:

  • bcrypt:

    • bcrypt is a program specifically designed to implement thebcrypt A library of hash algorithms. It is relatively simple and focuses on a single function, i.e., performing a password on thebcrypt Hash processing and validation.
    • Ideal for those who only needbcrypt Scenarios for hash algorithms.
    • The API provided is simple and straightforward, with fewer features.
  • Passlib:

    • Passlib is a more advanced cryptographic hash library that supports a variety of hash algorithms (e.g.bcryptPBKDF2Argon2 etc.) and provides richer functionality.
    • Ideal for scenarios that require support for multiple cryptographic hash algorithms and policies.
    • offeredCryptContext class makes it easy to manage and migrate multiple hash algorithms. It also provides an automatic upgrade mechanism for cryptographic hashes, as well as deprecation handling of old algorithms.

When you are sure that you only need to use thebcrypt algorithms, and when no additional complexity is required, thebcrypt It is a suitable choice. It is suitable for simple projects or when direct control is required of thesalt used in the case of parameters such as.

Passlib is suitable for complex projects, especially in scenarios where multiple hash algorithms need to be supported or where hash algorithms need to be migrated. Suitable for projects that require long-term maintenance, as it provides more configuration and security features.

bcryptLess flexible because it only supportsbcrypt Algorithm.No multiple hash algorithm selection or password policy management features. Easy to use and more intuitive code. If you only needbcrypt Algorithm.bcrypt The library may be easier to get started.

Passlib:Provides a high degree of flexibility and scalability. Different hash algorithms can be switched and configured as needed to manage complex password policies.pass (a bill or inspection etc)CryptContext, can easily manage transitions between different algorithms. Powerful but relatively complex, it requires more in-depth learning and understanding. However, its high-level API is designed to be user-friendly and can simplify many common tasks once familiarized.CryptContext is one of the classes used to manage multiple hash algorithms and cryptographic hash policies.

Sample code comparison:

bcrypt Example of use:

import bcrypt

password = b"supersecretpassword"
hashed = (password, ())

# Verify Password
if (password, hashed):
    print("Password matches!")
else:
    print("Password does not match.")

Passlib Example of use:

from  import CryptContext

# Create a CryptContext object
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

# hash password
password = "my_secret_password"
hashed_password = pwd_context.hash(password)
print("Hashed password:", hashed_password)

# Verify Password
is_correct = pwd_context.verify(password, hashed_password)
if is_correct:
    print("The password is correct.")
else:
    print("incorrect password")

Defines aCryptContext object for managing password hash algorithms.schemes=["bcrypt"] indicates that you want to use thebcrypt algorithm, and thedeprecated="auto" Indicates the automatic management of obsolete hash schemes.

utilizationpwd_context.hash() method hashes the password. The hash value generated is unique each time, and different hashes are generated even for the same password.

utilizationpwd_context.verify() method verifies that the given password matches the stored hash.

You can also createCryptContext object when passing more parameters to customize the password hash behavior, this approach can enhance the security of password storage. For example:

pwd_context = CryptContext(
    schemes=["bcrypt"],
    bcrypt__rounds=12  # bcrypt's hash rounds, default is 12
)

2、Use the specified salt for encryption

existPasslib Middle.bcrypt By default, the algorithm automatically generates a randomsaltIt's alsobcrypt A security feature of the If you want to use the specifiedsalt To perform encryption, it is important to note thatPasslib does not directly support the adoption of the specifiedsalt to perform hashing, as this may reduce security.

However, if you do need to use the specifiedsalt To perform hashing, you can use the following:

  1. Manual splicingsalt and passwords: Can be spliced manuallysalt and passwords and then hashing the results. However, this approach is only suitable for scenarios where risks are understood and security measures are ensured.

  2. utilizationbcrypt storehouse: Direct usebcrypt library for processing, which allows you to pass a specifiedsalt. However, note that this can be a security risk.

1) Usebcrypt library designationsalt

If you do need to specifysaltYou can use thebcrypt Coop.

import bcrypt

# Specified salt (must be 16 bytes, prefixed with b"$2b$")
salt = (rounds=12)  # Or use a custom 16-byte salt
print(f"Generated salt: {salt}")

# Password to be encrypted
password = "my_secret_password"

# Encrypt with the specified salt
hashed_password = (('utf-8'), salt)
print(f"Hashed password: {hashed_password}")

2) Manual splicingsalt and passwords

If you use thePassliband would like to use the specifiedsaltThe splicing can be done manually.salt and the password, and then hash this combined result. This approach is generally not recommended because it breaks thebcrypt The safety design principles of the

from  import CryptContext

# Create a CryptContext object
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

# Customizing salt
custom_salt = "my_custom_salt"

# Splicing salt and password
password = "my_secret_password"
password_with_salt = custom_salt + password

# Hashing the spliced string
hashed_password = pwd_context.hash(password_with_salt)
print("Hashed password with custom salt:", hashed_password)

caveat

  • Use of fixedsalt would reduce the security of the password hash because the samesalt and the same password will generate the same hash.
  • bcrypt was originally designed so that each generatedsalt All different, as a way to increase security.
  • If you need to use a fixed in a specific scenariosalt, always make sure that your system has adequate other security measures in place.

For the same password, the hash value obtained each time will be different, so some people will ask if the hash value obtained through pwd_context.hash can be compared correctly next time?

The answer is yes, usingpwd_context.hash() The generated hashes can be matched correctly in subsequent comparisons, even if the generated hashes look different each time.Passlib cap (a poem)bcrypt The design ensures this.

  • automaticsalt: Every time you usepwd_context.hash() When generating a new hash, thebcrypt Both automatically generate a randomsalt and embed it in the generated hash. As a result, even if the same password is hashed multiple times, the generated hash will be different each time.

  • verification process: During the validation process, thepwd_context.verify() will automatically extract the hash value from the storedsalt and recalculates the hash and then compares it to the provided hash. This means that even if the hashes are different, the validation still manages to match successfully.

Even if you run it every timepwd_context.hash(password) The hash values obtained are different (becausesalt different).pwd_context.verify(password, hashed_password) will still returnTrue, indicating successful password verification.

 

3. Encryption and decryption processing

Passlib It is mainly used for password hash processing and does not support encryption and decryption operations. If you need to encrypt and decrypt strings, or use asymmetric encryption, you need to use other libraries such ascryptography maybePyCryptodome

1)Symmetric encryption and decryption

For symmetric encryption, you can use thecryptography libraryFernetIt is an encryption scheme based on the AES algorithm.

mountingcryptography storehouse

pip install cryptography

Symmetric Encryption and Decryption Examples

from  import Fernet

# Generate key (note: key needs to be stored securely)
key = Fernet.generate_key()
cipher = Fernet(key)

# encrypted
message = "This is a secret message"
encrypted_message = (())
print("Encrypted:", encrypted_message)

# declassification
decrypted_message = (encrypted_message).decode()
print("Decrypted:", decrypted_message)

2) asymmetric encryption and decryption

For asymmetric encryption, you can use thecryptography libraryRSA Algorithm. Typically, asymmetric encryption is used to encrypt shorter messages or to encrypt symmetric keys.

Asymmetric Encryption and Decryption Examples

from  import rsa, padding
from  import serialization, hashes

# Generate private and public keys
private_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
)

public_key = private_key.public_key()

# encrypted
message = b"This is a secret message"
encrypted_message = public_key.encrypt(
    message,
    (
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)
print("Encrypted:", encrypted_message)

# declassification
decrypted_message = private_key.decrypt(
    encrypted_message,
    (
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)
print("Decrypted:", decrypted_message.decode())

3) Save and Load Keys

Keeping the private key:

private_pem = private_key.private_bytes(
    encoding=,
    format=,
    encryption_algorithm=()
)
with open('private_key.pem', 'wb') as f:
    (private_pem)

Load private key:

with open('private_key.pem', 'rb') as f:
    private_key = serialization.load_pem_private_key(
        (),
        password=None,
    )

Keeping the public key:

public_pem = public_key.public_bytes(
    encoding=,
    format=
)
with open('public_key.pem', 'wb') as f:
    (public_pem)

Load public key:

with open('public_key.pem', 'rb') as f:
    public_key = serialization.load_pem_public_key(())

 

We can choose the appropriate encryption methods and libraries according to the requirements and manage the keys properly during the total development process.