How do I get numbers from / dev / random using Python?
I'm trying to write a python script to check if / dev / random is random, but I can't get it to give me the number. My code looks like this:
with open ("/ dev / random", 'rb') as file: print f.read (10)
which I suppose should print 10 bytes from / dev / random, but instead of numbers, it outputs strange characters (non-standard letters and numbers). Any idea what I am doing wrong?
Thank!
source to share
Python has a built-in function for this (which will also use the corresponding method for other OSes) ...
import os
print os.urandom(10)
# '\xf1\x11xJOl\xab\xcc\xf0\xfd'
From the docs at http://docs.python.org/2/library/os.html#os.urandom
This function returns random bytes from an OS specific source of randomness. The returned data should be unpredictable for cryptographic applications, although its exact quality depends on the OS implementation. On UNIX-like system this will ask for / dev / urandom, and on Windows it will use CryptGenRandom. If no source of randomness is found, a NotImplementedError will be raised.
If you want these bytes to be a number, you can do so by converting as such:
>>> rand = os.urandom(10)
>>> int(rand.encode('hex'), 16)
1138412584848598544216317L
Although, /dev/random
and /dev/urandom
a little different from each other, you can use an existing .read()
op and just convert int
, if the difference is significant for you.
source to share
You get 10 bytes. Python won't automatically convert them to numbers.
I recommend that you grab the bytes in multiples of 4, then convert them to 32-bit unsigned integers, then scale them down to whatever you need.
EDIT: The old code showed the idea, but was loosely divided into functions. Here's the same basic idea, but now conveniently packaged in functions.
import os
import struct
_random_source = open("/dev/random", "rb")
def random_bytes(len):
return _random_source.read(len)
def unpack_uint32(bytes):
tup = struct.unpack("I", bytes)
return tup[0]
UINT32_MAX = 0xffffffff
def randint(low, high):
"""
Return a random integer in the range [low, high], including
both endpoints.
"""
n = (high - low) + 1
assert n >= 1
scale_factor = n / float(UINT32_MAX + 1)
random_uint32 = unpack_uint32(random_bytes(4))
result = int(scale_factor * random_uint32) + low
return result
def randint_gen(low, high, count):
"""
Generator that yields random integers in the range [low, high],
including both endpoints.
"""
n = (high - low) + 1
assert n >= 1
scale_factor = n / float(UINT32_MAX + 1)
for _ in range(count):
random_uint32 = unpack_uint32(random_bytes(4))
result = int(scale_factor * random_uint32) + low
yield result
if __name__ == "__main__":
# roll 3 dice individually with randint()
result = [randint(1, 6) for _ in range(3)]
print(result)
# roll 3 dice more efficiently with randint_gen()
print(list(randint_gen(1, 6, 3)))
source to share
It prints random characters, so just convert them to int with a function ord()
. Something like:
with open("/dev/random", 'rb') as file: print [ord(x) for x in file.read(10)]
This will print a list of 10 random numbers from 0 to 255. (I got:) [117, 211, 225, 24, 134, 145, 51, 234, 153, 89]
.
source to share