Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 433
user2835118 Avatar asked Jan 05 '14 17:01

user2835118


People also ask

Is Python random cryptographically secure?

Random numbers and data generated by the random class are not cryptographically protected. An output of all random module functions is not cryptographically secure, whether it is used to create a random number or pick random elements from a sequence.

What makes a random number generator cryptographically secure?

A PRNG is said to be cryptographically secure if, assuming that it operates over a wide enough unknown n-bit key, its output is computationally indistinguishable from uniformly random bits.

What module can be used to generate pseudo random numbers that are cryptographically secure?

The secrets module is used for generating cryptographically strong random numbers suitable for managing data such as passwords, account authentication, security tokens, and related secrets.

How do we generate cryptographically secure pseudorandom numbers?

A secure block cipher can be converted into a CSPRNG by running it in counter mode. This is done by choosing a random key and encrypting a 0, then encrypting a 1, then encrypting a 2, etc. The counter can also be started at an arbitrary number other than zero.


2 Answers

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.

like image 190
Tim Peters Avatar answered Oct 17 '22 02:10

Tim Peters


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)
'm\xd4\x94\x00x7\xbe\x04\xa2R'
>>> 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().

like image 50
thefourtheye Avatar answered Oct 17 '22 02:10

thefourtheye