"""Password hashing utilities (bcrypt)."""

import bcrypt


def hash_password(password: str) -> str:
    """Hash a password using bcrypt with cost factor 12.

    Args:
        password: Plain-text password.

    Returns:
        bcrypt hash as a utf-8 string (includes salt + cost factor).
    """
    salt = bcrypt.gensalt(rounds=12)
    return bcrypt.hashpw(password.encode("utf-8"), salt).decode("utf-8")


def verify_password(password: str, password_hash: str) -> bool:
    """Verify a password against a bcrypt hash.

    Args:
        password: Plain-text password to verify.
        password_hash: bcrypt hash string (as produced by :func:`hash_password`).

    Returns:
        True if the password matches the hash, False otherwise.
        Also returns False on malformed hash strings to avoid leaking
        exception details to callers.
    """
    try:
        return bcrypt.checkpw(
            password.encode("utf-8"),
            password_hash.encode("utf-8"),
        )
    except (ValueError, TypeError):
        return False
