def generate_random_bits(n_bits, rand_func=generate_random_bytes): """ Generates the specified number of random bits as a byte string. For example:: f(x) -> y such that f(16) -> 1111 1111 1111 1111; bytes_to_integer(y) => 65535L f(17) -> 0000 0001 1111 1111 1111 1111; bytes_to_integer(y) => 131071L :param n_bits: Number of random bits. if n is divisible by 8, (n / 8) bytes will be returned. if n is not divisible by 8, ((n / 8) + 1) bytes will be returned and the prefixed offset-byte will have `(n % 8)` number of random bits, (that is, `8 - (n % 8)` high bits will be cleared). The range of the numbers is 0 to (2**n)-1 inclusive. :param rand_func: Random bytes generator function. :returns: Bytes. """ if not builtins.is_integer(n_bits): raise TypeError("unsupported operand type: %r" % type(n_bits).__name__) if n_bits <= 0: raise ValueError("number of bits must be greater than 0.") # Doesn't perform any floating-point operations. quotient, remainder = divmod(n_bits, 8) random_bytes = rand_func(quotient) if remainder: offset = ord(rand_func(1)) >> (8 - remainder) random_bytes = builtins.byte(offset) + random_bytes return random_bytes
def generate_random_uint_between(low, high, rand_func=generate_random_bytes): """ Generates a random long integer between low and high, not including high. :param low: Low :param high: High :param rand_func: Random bytes generator function. :returns: Random unsigned long integer value. """ if not (builtins.is_integer(low) and builtins.is_integer(high)): raise TypeError("unsupported argument types(s): %r and %r" % (type(low).__name__, type(high).__name__)) if low >= high: raise ValueError("high value must be greater than low value.") substrate = high - low - 1 bits = builtins.integer_bit_size(substrate) value = generate_random_uint_atmost(bits, rand_func=rand_func) while value > substrate: value = generate_random_uint_atmost(bits, rand_func=rand_func) return low + value
def generate_random_sequence(length, pool, rand_func=generate_random_bytes): """ Generates a random sequence of given length using the sequence pool specified. :param length: The length of the random sequence. :param pool: A sequence of elements to be used as the pool from which random elements will be chosen. :returns: A list of elements randomly chosen from the pool. """ if not builtins.is_integer(length): raise TypeError("Length must be a positive integer: got `%r`" % type(length).__name__) if length <= 0: raise ValueError("length must be a positive integer: got %d" % length) return [random_choice(pool, rand_func) for _ in builtins.range(length)]
def generate_random_uint_atmost(n_bits, rand_func=generate_random_bytes): """ Generates a random unsigned integer with `n_bits` random bits. :param n_bits: Number of random bits to be generated at most. :param rand_func: Random bytes generator function. :returns: Returns an unsigned long integer with at most `n_bits` random bits. The generated unsigned long integer will be between 0 and (2**n_bits)-1 both inclusive. """ if not builtins.is_integer(n_bits): raise TypeError("unsupported operand type: %r" % type(n_bits).__name__) if n_bits <= 0: raise ValueError("number of bits must be greater than 0.") # Doesn't perform any floating-point operations. quotient, remainder = divmod(n_bits, 8) if remainder: quotient += 1 random_bytes = rand_func(quotient) mask = (1 << n_bits) - 1 return mask & integer.bytes_to_uint(random_bytes)