杰瑞科技汇

Python如何安全处理密码?

Of course! Using Python for password-related tasks is a common and powerful use case. However, it's crucial to handle passwords with extreme care, especially when it comes to security.

Python如何安全处理密码?-图1
(图片来源网络,侵删)

Let's break this down into three main scenarios:

  1. Generating Strong Passwords: Creating secure, random passwords.
  2. Storing Passwords Securely: The absolute DO NOT and the correct way to do it.
  3. Checking Password Strength: Evaluating how strong a user-provided password is.

Generating Strong Passwords

This is a great use case for Python. We'll use Python's built-in secrets module, which is designed for generating cryptographically strong random numbers suitable for managing data like passwords, account authentication, and security tokens.

Why secrets and not random? The random module is for modeling and simulation, not for security. The secrets module uses the best source of randomness your operating system can provide, making it unpredictable and secure.

Example: Generate a Password with Letters, Digits, and Symbols

import secrets
import string
import random
def generate_password(length=16):
    """
    Generates a cryptographically secure password.
    Args:
        length (int): The desired length of the password. Defaults to 16.
    Returns:
        str: The generated password.
    """
    # Define the character set
    letters = string.ascii_letters  # a-z, A-Z
    digits = string.digits          # 0-9
    symbols = string.punctuation    # !@#$%^&*()...
    # Combine all characters
    alphabet = letters + digits + symbols
    # Generate a password
    # We ensure at least one character from each category
    password = [
        secrets.choice(letters),
        secrets.choice(digits),
        secrets.choice(symbols)
    ]
    # Fill the rest of the password with random choices from the full alphabet
    for _ in range(length - 3):
        password.append(secrets.choice(alphabet))
    # Shuffle the list to ensure the first 3 characters aren't predictable
    random.shuffle(password)
    # Convert the list to a string
    return "".join(password)
# --- Usage ---
if __name__ == "__main__":
    new_password = generate_password(20)
    print(f"Generated Password: {new_password}")
    # Example of a shorter password
    short_password = generate_password(12)
    print(f"Generated Short Password: {short_password}")

Key Takeaways:

Python如何安全处理密码?-图2
(图片来源网络,侵删)
  • secrets.choice(): Picks a random, secure character from a sequence.
  • string module: Provides handy constants like ascii_letters, digits, and punctuation.
  • random.shuffle(): Used to mix up the characters so the password isn't predictable (e.g., doesn't always start with a letter).

Storing Passwords Securely (The Most Important Part)

This is a critical security rule.

🚫 NEVER DO THIS: Store Plain-Text Passwords

Storing passwords in plain text in a file or database is a massive security risk. If your database is ever compromised, all user passwords will be exposed.

# 🚫 AVOID THIS CODE AT ALL COSTS
import json
# DO NOT store passwords like this
user_credentials = {
    "alice": "password123",
    "bob": "super_secret_password"
}
with open("users.json", "w") as f:
    json.dump(user_credentials, f)

✅ THE CORRECT WAY: Hashing with Salt

The standard and secure practice is to hash passwords. A hash is a one-way function: you can turn a password into a hash, but you can't turn the hash back into the password.

Even better, you should use a salt. A salt is a random piece of data that you add to each password before hashing. This ensures that even if two users have the same password (e.g., "password123"), their stored hashes will be completely different.

Python如何安全处理密码?-图3
(图片来源网络,侵删)

We'll use the bcrypt library, which is the gold standard for password hashing. It's slow and computationally expensive, which is a good thing because it makes brute-force attacks much harder.

First, install bcrypt:

pip install bcrypt

Example: Hashing and Verifying Passwords

import bcrypt
import os
def hash_password(password: str) -> str:
    """
    Hashes a password using bcrypt with a salt.
    Args:
        password (str): The plain-text password to hash.
    Returns:
        str: The hashed password, including the salt.
    """
    # Generate a salt. The 'gensalt' function creates a random salt.
    # The 'rounds' parameter controls the computational cost (higher is more secure).
    salt = bcrypt.gensalt(rounds=12)
    # Hash the password
    hashed_password = bcrypt.hashpw(password.encode('utf-8'), salt)
    # The result is a bytes object, which we can decode to a string for storage
    return hashed_password.decode('utf-8')
def check_password(plain_password: str, hashed_password_str: str) -> bool:
    """
    Checks if a plain-text password matches a stored hash.
    Args:
        plain_password (str): The password provided by the user.
        hashed_password_str (str): The stored, hashed password string.
    Returns:
        bool: True if the password matches, False otherwise.
    """
    # bcrypt needs the hash to be in bytes for comparison
    hashed_password_bytes = hashed_password_str.encode('utf-8')
    # Hash the provided password with the salt from the stored hash
    # bcrypt.checkpw handles the salt extraction and comparison
    return bcrypt.checkpw(plain_password.encode('utf-8'), hashed_password_bytes)
# --- Usage ---
if __name__ == "__main__":
    # 1. User registers with a new password
    my_password = "a_very_strong_and_secret_password_123!"
    hashed_pw = hash_password(my_password)
    print(f"Original Password: {my_password}")
    print(f"Hashed Password:   {hashed_pw}")
    # Store this hashed_pw in your database for the user
    # 2. User tries to log in
    login_attempt_1 = "a_very_strong_and_secret_password_123!"
    login_attempt_2 = "wrong_password"
    # Check the first attempt (should be True)
    is_correct_1 = check_password(login_attempt_1, hashed_pw)
    print(f"\nLogin attempt '{login_attempt_1}' is correct: {is_correct_1}")
    # Check the second attempt (should be False)
    is_correct_2 = check_password(login_attempt_2, hashed_pw)
    print(f"Login attempt '{login_attempt_2}' is correct: {is_correct_2}")

Checking Password Strength

This is a different task from security. Here, we're not making the password secure, but we're giving the user feedback on how strong their chosen password is against common attacks (like dictionary attacks or guessing).

This is a heuristic-based approach, not a security measure. The goal is to encourage users to create better passwords.

import re
def check_password_strength(password: str) -> tuple[str, int]:
    """
    Evaluates the strength of a password based on common criteria.
    Args:
        password (str): The password to check.
    Returns:
        tuple[str, int]: A tuple containing a feedback message and a score (0-5).
    """
    score = 0
    feedback = []
    # Criteria
    if len(password) >= 8:
        score += 1
    else:
        feedback.append("Password should be at least 8 characters long.")
    if re.search(r"[a-z]", password):
        score += 1
    else:
        feedback.append("Include at least one lowercase letter.")
    if re.search(r"[A-Z]", password):
        score += 1
    else:
        feedback.append("Include at least one uppercase letter.")
    if re.search(r"\d", password):
        score += 1
    else:
        feedback.append("Include at least one number.")
    if re.search(r"[!@#$%^&*(),.?\":{}|<>]", password):
        score += 1
    else:
        feedback.append("Include at least one special character (!, @, #, etc.).")
    # Final feedback message
    if not feedback:
        feedback_message = "Strong password!"
    else:
        feedback_message = "Weak password. Consider the following:\n" + "\n".join(feedback)
    return feedback_message, score
# --- Usage ---
if __name__ == "__main__":
    test_passwords = [
        "short",
        "password",
        "Password123",
        "P@ssw0rd!",
        "ThisIsAVeryLongAndStrongPassword123!"
    ]
    for pwd in test_passwords:
        message, strength_score = check_password_strength(pwd)
        print(f"\nPassword: '{pwd}'")
        print(f"Score: {strength_score}/5")
        print(f"Feedback: {message}")

Summary

Task Python Tool/Method Security Level Purpose
Generating secrets module High Create unpredictable passwords for users.
Storing bcrypt library Critical Securely store passwords in a database.
Checking Strength re module, heuristics Low Provide user feedback to encourage better passwords.
分享:
扫描分享到社交APP
上一篇
下一篇