60 lines
1.7 KiB
Python
60 lines
1.7 KiB
Python
from passlib.context import CryptContext
|
|
import string
|
|
import secrets
|
|
|
|
# Create a password context for hashing and verifying
|
|
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
|
|
|
def generate_reset_password_token():
|
|
return secrets.token_urlsafe(32)
|
|
|
|
def hash_password(password: str) -> str:
|
|
"""
|
|
Hash a password using bcrypt
|
|
"""
|
|
return pwd_context.hash(password)
|
|
|
|
def verify_password(plain_password: str, hashed_password: str) -> bool:
|
|
"""
|
|
Verify a password against a hash
|
|
"""
|
|
return pwd_context.verify(plain_password, hashed_password)
|
|
|
|
|
|
def generate_secure_password(length: int = 16, include_special: bool = True) -> str:
|
|
"""
|
|
Generate a cryptographically secure random password
|
|
|
|
Args:
|
|
length: Length of the password (default 16)
|
|
include_special: Include special characters (default True)
|
|
|
|
Returns:
|
|
A secure random password string
|
|
"""
|
|
# Define character sets
|
|
lowercase = string.ascii_lowercase
|
|
uppercase = string.ascii_uppercase
|
|
digits = string.digits
|
|
special_chars = string.punctuation if include_special else ""
|
|
|
|
# Combined character set
|
|
all_chars = lowercase + uppercase + digits + special_chars
|
|
|
|
# Ensure at least one character from each required group
|
|
password = [
|
|
secrets.choice(lowercase),
|
|
secrets.choice(uppercase),
|
|
secrets.choice(digits)
|
|
]
|
|
|
|
if include_special and special_chars:
|
|
password.append(secrets.choice(special_chars))
|
|
|
|
# Fill remaining length with random characters
|
|
password.extend(secrets.choice(all_chars) for _ in range(length - len(password)))
|
|
|
|
# Shuffle the password characters
|
|
secrets.SystemRandom().shuffle(password)
|
|
|
|
return ''.join(password) |