Source code for streamlit_authenticator.utilities.hasher

"""
Script description: Handles secure hashing and validation of plain text passwords using bcrypt.

Libraries Imported:
-------------------
- re: Implements regular expressions for pattern matching.
- bcrypt: Provides secure password hashing.
- typing: Provides standard type hints for Python functions.
"""

import re
import bcrypt
from typing import Dict, List


[docs] class Hasher: """ This class provides methods for hashing and verifying passwords. """ def __init__(self) -> None: pass
[docs] @classmethod def check_pw(cls, password: str, hashed_password: str) -> bool: """ Verifies if a plain text password matches a hashed password. Parameters ---------- password : str The plain text password. hashed_password : str The hashed password to compare against. Returns ------- bool True if the password matches the hash, False otherwise. """ return bcrypt.checkpw(password.encode(), hashed_password.encode())
[docs] @classmethod def hash(cls, password: str) -> str: """ Hashes a plain text password using bcrypt. Parameters ---------- password : str The plain text password. Returns ------- str The securely hashed password. """ return bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode()
[docs] @classmethod def hash_list(cls, passwords: List[str]) -> List[str]: """ Hashes a list of plain text passwords. Parameters ---------- passwords : list of str The list of plain text passwords to be hashed. Returns ------- list of str The list of securely hashed passwords. """ return [cls.hash(password) for password in passwords]
[docs] @classmethod def hash_passwords(cls, credentials: Dict[str, Dict[str, str]]) -> Dict[str, Dict[str, str]]: """ Hashes all plain text passwords in a credentials dictionary. Parameters ---------- credentials : dict Dictionary containing usernames as keys and user details as values. Returns ------- dict The credentials dictionary with all passwords securely hashed. """ usernames = credentials['usernames'] for _, user in usernames.items(): password = user['password'] if not cls.is_hash(password): hashed_password = cls.hash(password) user['password'] = hashed_password return credentials
[docs] @classmethod def is_hash(cls, hash_string: str) -> bool: """ Determines if a given string is a bcrypt hash. Parameters ---------- hash_string : str The string to check. Returns ------- bool True if the string is a valid bcrypt hash, False otherwise. """ bcrypt_regex = re.compile(r'^\$2[aby]\$\d+\$.{53}$') return bool(bcrypt_regex.match(hash_string))