import hashlib def H(salt: bytes, left: bytes, right: bytes) -> bytes: """Pomocná hashovacia funkcia SHAKE-128 s výstupom dĺžky 6 bajtov.""" shake = hashlib.shake_128() shake.update(salt + left + right) return shake.digest(6) def hash_password(password: str, salt: bytes) -> bytes: """ Spočíta odtlačok hesla dĺžky 16 znakov pomocou stromu. Alphabet: {0..9, A..Z, a..z, ?, !} """ if len(password) != 16: raise ValueError("Heslo musí mať presne 16 znakov.") # 1. Príprava listov podľa vzoru: p1, p2, p2, p3, p3, p4, ..., p16, p1 # Každý znak reprezentuje jeden list (spolu 32 listov) leaves = [] for i in range(16): p_current = password[i].encode('utf-8') p_next = password[(i + 1) % 16].encode('utf-8') leaves.extend([p_current, p_next]) # 2. Budovanie stromu zdola nahor current_level = leaves while len(current_level) > 1: next_level = [] # Prechádzame dvojice aktuálnej úrovne for i in range(0, len(current_level), 2): left = current_level[i] right = current_level[i + 1] # Výpočet hashu pre rodičovský vrchol parent_hash = H(salt, left, right) next_level.append(parent_hash) current_level = next_level # Koreň stromu (výsledný odtlačok) return current_level[0] # --- Príklad použitia --- if __name__ == "__main__": test_password = "Ab1?Cd2!Ef3?Gh4!" # 16 znakov z povolenej abecedy test_salt = b"salt12" # soľ result = hash_password(test_password, test_salt) print(f"Výsledný odtlačok (hex): {result.hex()}")