#!/usr/bin/python3 from _hashlib import HASH from hashlib import sha512 from time import time from typing import Callable def long_to_bytes(value: int, big_endian: bool) -> bytes: # https://stackoverflow.com/a/14527004/3810747 bytes_string = unhexlify(('%%0%dx' % (((width := value.bit_length()) + 8 - ((width % 8) or 8)) // 4)) % value) return bytes_string if big_endian else bytes_string[::-1] def bytes_to_long(values: Union[bytes, bytearray], big_endian: bool) -> int: return sum(v << (8 * i) for i, v in enumerate(values if big_endian else reversed(values))) T_HASHING_FXN = Callable[[Union[ByteString, memoryview]], HASH] def hash_digest(data: bytes, hash_fxn: T_HASHING_FXN) -> bytes: return hash_fxn(data).digest() def new_seed(r_bits: Callable[[int], int], seed_fxn: Callable[[int], Any], s_round_bits: int = 2056, n_rounds: int = 512, hash_fxn: T_HASHING_FXN = sha512) -> int: built_seed = r_bits(s_round_bits) for _ in range(n_rounds): seed = long_to_bytes(r_bits(s_round_bits), True) seed += hash_digest(long_to_bytes(built_seed, True), hash_fxn) seed += long_to_bytes(int(time() * 10_000_000), True) seed += hash_digest(seed, hash_fxn) seed = sum((_byte << (8 * _byte_group)) for _byte, _byte_group in zip(seed, range(len(seed), -1, -1))) seed_fxn(seed) built_seed = seed return built_seed