import os import hashlib class password: """ This class is responsible for managing passwords and passwords hashes generating. """ def __init__(self, target: str, lenght: int = 48) -> None: """ This is password initialized. It generate new password hash from the password. Lenght of the hash could be changed. target: str - Target password lenght: int - Lenght of the password hash (default: 48) """ self.__lenght = lenght self.__target = target @property def lenght(self) -> int: """ This return lenght of the hash. """ return self.__lenght @property def __salt(self) -> str: """ This return random salt with lenght of the hash." """ return os.urandom(self.lenght).hex() @property def separator(self) -> str: """ This return separator between salt and hash. """ return "." def __generate(self, salt: str) -> str: """ This generate new hash from the password and salt. salt: str - Salt to use when generating return: str - Password hash generated from given salt """ salted = salt + self.__target binary = hashlib.shake_256(salted.encode()) hashed = binary.hexdigest(self.lenght) full = salt + self.separator + hashed return full @property def result(self) -> str: """ This generate new hash from the password. return: str - New password hash with random salt """ return self.__generate(self.__salt) def validate(self, hashed: str) -> bool: """ This function validate password hash. When passwords match, then return True, when password from the class not match with given hash, then return False. hashed: str - Password hash to check return: bool - True when passwords match, False if not """ position = hashed.find(self.separator) if position == -1: return False salt = hashed[:position] full = hashed[position + len(self.separator):] if len(salt) != len(full): return False if len(full) != self.lenght * 2: return False return self.__generate(salt) == hashed