I'm looking to get n random bytes as a bytearray or bytes, as os.urandom
does.
However I need to be able to set a random seed so the value is reproducable.
def urandom_from_random(rng, length):
return bytes([rng.randint(0, 255) for i in range(length)])
import random
rng = random.Random(42)
data = urandom_from_random(rng, 120)
print(data)
The script above works, but isn't very efficient.
Is there a more direct way to do this besides creating many ints and converting them to bytes?
Note:
os. urandom() method is used to generate a string of size random bytes suitable for cryptographic use or we can say this method generates a string containing random characters. Syntax: os.urandom(size) Parameter: size: It is the size of string random bytes.
Python Random seed() Method The seed() method is used to initialize the random number generator. The random number generator needs a number to start with (a seed value), to be able to generate a random number. By default the random number generator uses the current system time.
/dev/urandom is widely considered safe for all cryptographic purposes, except by the most paranoid people."
The /dev/urandom device provides a reliable source of random output, however the output will not be generated from an equal amount of random input if insufficient input is available. Reads from the /dev/urandom device always return the quantity of output requested without blocking.
Most random data generated with Python is not fully random in the scientific sense of the word. Rather, it is pseudorandom: generated with a pseudorandom number generator (PRNG), which is essentially any algorithm for generating seemingly random but still reproducible data.
I think the closest function in random
to what you want is getrandbits
. It returns an integer with the requested number of bits. If you want to turn that into a bytes
instance, you can use int.to_bytes
.
Here's a quick function that pairs those two together:
def urandom_from_random(rng, length):
if length == 0:
return b''
integer = rng.getrandbits(length * 8)
result = integer.to_bytes(length, sys.byteorder)
return result
The byte order you specify to to_bytes
shouldn't matter. I tell it to use the system's native byte order, but I don't actually know if that makes it any faster than it would be otherwise.
This is a modified version of @Blckknght's answer that takes into account the internal INT_MAX
limit in getrandbits
.
def urandom_from_random(rng, length):
if length == 0:
return b''
import sys
chunk_size = 65535
chunks = []
while length >= chunk_size:
chunks.append(rng.getrandbits(
chunk_size * 8).to_bytes(chunk_size, sys.byteorder))
length -= chunk_size
if length:
chunks.append(rng.getrandbits(
length * 8).to_bytes(length, sys.byteorder))
result = b''.join(chunks)
return result
Example use:
import random
rng = random.Random(42)
print(len(urandom_from_random(rng, 300000000)))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With