Skip to content

Passwords

bluefox_auth.passwords

Direct bcrypt password hashing — no wrapper libraries.

Functions

hash_password

def hash_password(plain: str) -> str

Hash a plaintext password with bcrypt. Returns a string like $2b$12$....

verify_password

def verify_password(plain: str, hashed: str) -> bool

Verify a plaintext password against a bcrypt hash.

verify_password_timing_safe

def verify_password_timing_safe(plain: str, hashed: str | None) -> bool

Verify a password, falling back to a pre-computed dummy hash if hashed is None. This prevents timing-based user enumeration — the bcrypt comparison takes the same amount of time whether the user exists or not.

Used by the login flow:

# If user not found, still runs bcrypt against a dummy hash
if user is None:
    verify_password_timing_safe(data.password, None)
    raise HTTPException(401, "Invalid credentials")

if not verify_password_timing_safe(data.password, user.password_hash):
    raise HTTPException(401, "Invalid credentials")