Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
htpasswd.py82 linesDownload Raw Back to utils
1"""2A standalone, minimal htpasswd parser.3 4This implementation currently supports bcrypt and SHA1 passwords. SHA1 is insecure.5"""6 7from __future__ import annotations8 9import base6410import hashlib11from pathlib import Path12 13import bcrypt14 15 16class HtpasswdFile:17    def __init__(self, content: str):18        """19        Create a HtpasswdFile from a string.20        """21        self.users: dict[str, str] = {}22        for line in content.splitlines():23            line = line.strip()24            if not line or line.startswith("#"):25                continue26            if ":" not in line:27                raise ValueError(f"Malformed htpasswd line: {line!r}")28            user, pwhash = line.split(":", 1)29            if not user:30                raise ValueError(f"Malformed htpasswd line: {line!r}")31 32            is_sha = pwhash.startswith("{SHA}")33            is_bcrypt = pwhash.startswith(("$2y$", "$2b$", "$2a$"))34            if not is_sha and not is_bcrypt:35                raise ValueError(f"Unsupported htpasswd format for user {user!r}")36 37            self.users[user] = pwhash38 39    @classmethod40    def from_file(cls, path: Path) -> HtpasswdFile:41        """42        Initializes and loads an htpasswd file.43 44        Args:45            path: The path to the htpasswd file.46 47        Raises:48            OSError: If the file cannot be read.49            ValueError: If the file is malformed.50        """51        try:52            content = path.read_text("utf-8")53        except FileNotFoundError:54            raise OSError(f"Htpasswd file not found: {path}") from None55        return cls(content)56 57    def check_password(self, username: str, password: str) -> bool:58        """59        Checks if a username and password combination is valid.60 61        Args:62            username: The username to check.63            password: The password to check.64 65        Returns:66            True if the password is valid, False otherwise.67        """68        pwhash = self.users.get(username)69        if pwhash is None:70            return False71 72        pwhash = pwhash.split(":", 1)[0]73 74        if pwhash.startswith("{SHA}"):75            # Apache's {SHA} is base64-encoded SHA-1.76            # https://httpd.apache.org/docs/2.4/misc/password_encryptions.html77            digest = hashlib.sha1(password.encode("utf-8")).digest()78            expected = base64.b64encode(digest).decode("ascii")79            return pwhash[5:] == expected80        else:  # pwhash.startswith(("$2y$", "$2b$", "$2a$")):81            return bcrypt.checkpw(password.encode("utf-8"), pwhash.encode("utf-8"))82 
codekingpro/portable-devtools · Team Ai