Randomness is found everywhere, from Cryptography to Machine Learning. Without random number generation, many things would be impossible to accomplish, in the case of cryptography, everything would be predictable and easy to break.
A random number generator (RNG) is a system (software or hardware component) that generates a sequence of random numbers from a true source of randomness, which can be reliable for cryptographic use. However, there is pseudo-random number generators (PRNG), which generate random numbers that look random, but are actually deterministic, which means we can reproduce it if the state (or seed) of the PRNG is known.
In this tutorial, you will learn how you can generate random numbers, strings and bytes in Python using built-in random module, this module implements pseudo-random number generators (which means, you shouldn't use it for cryptographic use, such as key or password generation).
We will also explore secrets module for generating cryptographically secure random numbers suitable for passwords, encryption keys, account authentication and related secrets.
To generate random integers, we can either use random.randint() or random.randrange() functions, let's see the difference:
import random import os import string # generate random integer between a and b (including a and b) randint = random.randint(1, 500) print("randint:", randint) # generate random integer from range randrange = random.randrange(0, 500, 5) print("randrange:", randrange)
randint: 87 randrange: 80
random.randint() function returns a random integer between a and b (in this case, 1 and 500) which includes a and b, in other words: a<= x <=b.
Whereas random.randrange() chooses a random item from that range (start=0, stop=500, step=5), which can be 0, 5, 10, 15 and so on, until 500.
Let's say we have a big list of elements and we want to randomly select one item, random.choice() comes into the rescue:
# get a random element from this list choice = random.choice(["hello", "hi", "welcome", "bye", "see you"]) print("choice:", choice)
This will randomly choose one element from that list, here is an output:
If you wish to select more than one element once, you can use random.choices() function instead:
# get 5 random elements from 0 to 1000 choices = random.choices(range(1000), k=5) print("choices:", choices)
This will select 5 elements from that range:
choices: [889, 832, 537, 110, 130]
You can also generate floating point numbers:
# generate a random floating point number from 0.0 <= x <= 1.0 randfloat = random.random() print("randfloat between 0.0 and 1.0:", randfloat)
randfloat between 0.0 and 1.0: 0.49979177801639296
If you want to generate a float between 2 numbers, you can use random.uniform() function:
# generate a random floating point number such that a <= x <= b randfloat = random.uniform(5, 10) print("randfloat between 5.0 and 10.0:", randfloat)
This will generate any float between 5 and 10:
randfloat between 5.0 and 10.0: 5.258643397238765
In order to randomly shuffle any iterable in Python, you can use random.shuffle() function, here is an example:
l = list(range(10)) print("Before shuffle:", l) random.shuffle(l) print("After shuffle:", l)
Before shuffle: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] After shuffle: [7, 8, 4, 5, 6, 9, 2, 1, 0, 3]
There isn't a direct way to generate random strings in random module. However, we can use random.sample() or random.choices() functions to randomly select characters from a list of characters:
# generate a random string randstring = ''.join(random.sample(string.ascii_letters, 16)) print("Random string with 16 characters:", randstring)
This will generate 16 characters (as we specified) from string.ascii_letters which includes all ASCII characters:
Random string with 16 characters: MjIRHEGnxCSNeAiv
You can also add numbers by using string.ascii_letters + string.digits, or you can use only lowercase characters by using string.ascii_lowercase.
As we mentioned previously, random module is extremely insecure for password generation or any cryptographic use. In fact, you can even use random.seed() function to set the seed of randomness, which will generate the same sequence of numbers everytime you run the program, this can be useful for machine learning or other purposes.
However, for cryptographic use, you can use secrets module instead, the below lines of code randomly generates different types of data securely:
# crypto-safe byte generation randbytes_crypto = os.urandom(16) print("Random bytes for crypto use using os:", randbytes_crypto) # or use this randbytes_crypto = secrets.token_bytes(16) print("Random bytes for crypto use using secrets:", randbytes_crypto) # crypto-secure string generation randstring_crypto = secrets.token_urlsafe(16) print("Random strings for crypto use:", randstring_crypto) # crypto-secure bits generation randbits_crypto = secrets.randbits(16) print("Random 16-bits for crypto use:", randbits_crypto)
Here is the output:
Random bytes for crypto use using os: b'\xf4\xa1\xed\xb3\xef)\xfe\xd2\xe6\x86\xdb&=\xff\xf5\x9c' Random bytes for crypto use using secrets: b'\x99^\x96\x90\xe93[\x1d\x86C\xe8\xcf\x1f\xa3\x06\x86' Random strings for crypto use: RJDD-8iCEsAuDC1-N9EbQA Random 16-bits for crypto use: 2371
Learn also: How to Use Hash Algorithms in Python using hashlib.
In practice, you should use random module for statistical modeling, simulation, machine learning and other purposes (you can also use numpy's random module to generate random arrays), to generate random data reproducible, which are significantly faster than cryptographically secure generators.
You should only use secrets module for cryptographic applications where data security is critical.
For further information, you can check Python's official documentation for different modules used in this tutorial:
To learn more about cryptography, I highly suggest you to get the awesome Serious Cryptography book and read it !
Happy Generating ♥View Full Code