# How can I create a random number that is cryptographically secure in python?

## Question:

I’m making a project in python and I would like to create a random number that is cryptographically secure, How can I do that? I have read online that the numbers generated by the regular randomizer are not cryptographically secure, and that the function `os.urandom(n)` returns me a string, and not a number.

## Answers:

You can get a list of random numbers by just applying `ord` function over the bytes returned by `os.urandom`, like this

``````>>> import os
>>> os.urandom(10)
'mxd4x94x00x7xbex04xa2R'
>>> type(os.urandom(10))
<type 'str'>
>>> map(ord, os.urandom(10))
[65, 120, 218, 135, 66, 134, 141, 140, 178, 25]
``````

Quoting `os.urandom` documentation,

Return a string of `n` random bytes suitable for cryptographic use.

This function returns random bytes from an OS-specific randomness source. The returned data should be unpredictable enough for cryptographic applications, though its exact quality depends on the OS implementation. On a UNIX-like system this will query `/dev/urandom`, and on Windows it will use `CryptGenRandom()`.

Since you want to generate integers in some specific range, it’s a lot easier to use the `random.SystemRandom` class instead. Creating an instance of that class gives you an object that supports all the methods of the `random` module, but using `os.urandom()` under the covers. Examples:

``````>>> from random import SystemRandom
>>> cryptogen = SystemRandom()
>>> [cryptogen.randrange(3) for i in range(20)] # random ints in range(3)
[2, 2, 2, 2, 1, 2, 1, 2, 1, 0, 0, 1, 1, 0, 0, 2, 0, 0, 0, 0]
>>> [cryptogen.random() for i in range(3)]  # random floats in [0., 1.)
[0.2710009745425236, 0.016722063038868695, 0.8207742461236148]
``````

Etc. Using `urandom()` directly, you have to invent your own algorithms for converting the random bytes it produces to the results you want. Don’t do that ðŸ˜‰ `SystemRandom` does it for you.

Note this part of the docs:

class random.SystemRandom([seed])

Class that uses the os.urandom() function for generating random numbers from sources provided by the operating system. Not available on all systems. Does not rely on software state and sequences are not reproducible. Accordingly, the seed() and jumpahead() methods have no effect and are ignored. The getstate() and setstate() methods raise NotImplementedError if called.

If you want an `n`-bit random number, under Python 2.4+, the easiest method I’ve found is

``````import random
random.SystemRandom().getrandbits(n)
``````

Note that `SystemRandom` uses `os.urandom()`, so the result of this method is only as good as your system’s `urandom()` implementation.

Python 3.6 introduces a new secrets module, which “provides access to the most secure source of randomness that your operating system provides.” In order to generate some cryptographically secure numbers, you can call `secrets.randbelow()`.

``````secrets.randbelow(n)
``````

which will return a number between 0 and `n`.

To generate a cryptographically secure pseudorandom integer, you can use the following code:

``````int(binascii.hexlify(os.urandom(n)),16)
``````

Where `n` is an integer and, the larger `n` is, the larger the integer generated is.

You will have to import `os` and `binascii` first.

The result of this code can vary by platform.

Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.