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!

+3


source to share


4 answers


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.

+9


source


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)))

      

+8


source


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]

.

+1


source


In Python 3.2 and up, the following is shorter and probably faster than the solutions in the older answers:

with open("/dev/random", 'rb') as f:
    print(int.from_bytes(f.read(10), 'big'))

      

This prints one 80 bit number (range 0 to 2 ^ 80-1 inclusive).

0


source







All Articles