"""Password hashing and verification. Ported from net.i2p.util.PasswordManager. """ from __future__ import annotations import hashlib import os import secrets class PasswordManager: """Hash and verify passwords using salted SHA-256.""" def create_hash(self, password: str) -> str: """Create a salted hash of a password. Returns 'salt_hex:hash_hex'. """ salt = os.urandom(16) h = hashlib.sha256(salt + password.encode("utf-8")).hexdigest() return f"{salt.hex()}:{h}" def check_password(self, password: str, stored_hash: str) -> bool: """Check a password against a stored hash.""" try: salt_hex, expected_hash = stored_hash.split(":", 1) salt = bytes.fromhex(salt_hex) actual = hashlib.sha256(salt + password.encode("utf-8")).hexdigest() return secrets.compare_digest(actual, expected_hash) except (ValueError, IndexError): return False def generate_password(self, length: int = 32) -> str: """Generate a random password.""" return secrets.token_urlsafe(length)