46 lines
1.2 KiB
Python
46 lines
1.2 KiB
Python
"""Algorithm interface and registry for password hashing."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Protocol
|
|
|
|
|
|
class Algorithm(Protocol):
|
|
"""Protocol defining the interface for password hashing algorithms."""
|
|
|
|
identifier: str
|
|
|
|
def hash(self, password: str, **kwargs) -> tuple[str, str]:
|
|
"""Hash a password and return (salt_b64, hash_b64)."""
|
|
...
|
|
|
|
def verify(self, password: str, salt_b64: str, hash_b64: str, **kwargs) -> bool:
|
|
"""Verify a password against stored salt and hash."""
|
|
...
|
|
|
|
|
|
# Algorithm registry
|
|
_ALGORITHMS: dict[str, Algorithm] = {}
|
|
|
|
|
|
def register_algorithm(algo: Algorithm) -> None:
|
|
"""Register an algorithm in the global registry."""
|
|
_ALGORITHMS[algo.identifier] = algo
|
|
|
|
|
|
def get_algorithm(name: str) -> Algorithm:
|
|
"""Get an algorithm by name from the registry."""
|
|
if name not in _ALGORITHMS:
|
|
raise ValueError(f"Unknown algorithm: {name}")
|
|
return _ALGORITHMS[name]
|
|
|
|
|
|
def list_algorithms() -> list[str]:
|
|
"""Return list of registered algorithm identifiers."""
|
|
return sorted(_ALGORITHMS.keys())
|
|
|
|
|
|
# Import to auto-register algorithms
|
|
import pbkdf2_algorithm # noqa: E402, F401
|
|
import argon2_algorithm # noqa: E402, F401
|