A Python port of the Invisible Internet Project (I2P)
1"""Password hashing and verification.
2
3Ported from net.i2p.util.PasswordManager.
4"""
5
6from __future__ import annotations
7
8import hashlib
9import os
10import secrets
11
12
13class PasswordManager:
14 """Hash and verify passwords using salted SHA-256."""
15
16 def create_hash(self, password: str) -> str:
17 """Create a salted hash of a password.
18
19 Returns 'salt_hex:hash_hex'.
20 """
21 salt = os.urandom(16)
22 h = hashlib.sha256(salt + password.encode("utf-8")).hexdigest()
23 return f"{salt.hex()}:{h}"
24
25 def check_password(self, password: str, stored_hash: str) -> bool:
26 """Check a password against a stored hash."""
27 try:
28 salt_hex, expected_hash = stored_hash.split(":", 1)
29 salt = bytes.fromhex(salt_hex)
30 actual = hashlib.sha256(salt + password.encode("utf-8")).hexdigest()
31 return secrets.compare_digest(actual, expected_hash)
32 except (ValueError, IndexError):
33 return False
34
35 def generate_password(self, length: int = 32) -> str:
36 """Generate a random password."""
37 return secrets.token_urlsafe(length)