Introduction
Today we will discuss on everything you need to know about How To Generate Truly Randomness In Python in simple and easy to follow guide.
Did you know that Python does not offer a way to do this out of the box?
Today I will break down three different ways on how to accomplish this task.
- Discuss what is a true random number
- We will provide some ways of doing this
- Will show you how to include this in your Python Code
If you would like to learn more on the standard Python random library you can find more information here.
I have been working in the Software industry for over 23 years now and I have been a software architect, manager, developer and engineer. I am a machine learning and crypto enthusiast with emphasis in security. I have experience in various industries such as entertainment, broadcasting, healthcare, security, education, retail and finance.
Prerequisites
In order to get started with activating and offering a way on How To Generate Truly Randomness In Python you will need some basic stuff setup on your system to get going.
- First you need a Python interpreter installed on your machine which you can install from here
- You will need to make sure you are using Python 3 if you want to follow this guide as all examples will be related to that, but could be compatible with Python 2 as well with minor changes
- Your environment needs to support a shell where we will invoke Python from to experiment
Understanding the Current Random Functions
First and foremost we want to make sure that we understand the limitations of the existing random functionality that Python has and how we can solve the problems and the need to extend it.
The basic functionality for Python to generate a random number or string is reliant upon the fact that it works without having any human input seed value. Lets explain what this means in simple terms so we can further understand how it can be a problem.
A seed is basically a value a random function uses to initialize it’s state and use to generate a random number, without a seed you don’t have anything other than a flat static set of values which isn’t random.
Some common sources of seeding that random functions use are:
- Time
- Date
- Hardware specific values such as:
- MAC Address
- CPU Identifier
- Graphics Card Identifier
The list can go on and on but all of the above share one common problem!
The problem above is that all those values are predictable if you have access to the machine. Lets take for example the MAC Address identifier of the machine. If someone had access and was trying to use the random function they can easily see this using the ifconfig/ipconfig command. Furthermore some of that may be publicly available in the network so that increases the attack surface to an even remote attack to the random number generator. So in this case the selection of the MAC address is a really bad choice to use for randomness.
If we were to use some other value which was lets say a bit more secret to the user like the CPU or GPU identifier they’d still be open to being read locally on the system resulting to a problem when using a random value.
Time and date are also bad choices as the person trying to guess your random number will be able to know it based on when it was provided/generated.
How Does Random in Python Work
Since the Python random function has to use one of the above sources it simply cannot be held as a good choice for using as a random source. This is the reason it is also called as Pseudo Random function. The word pseudo in this case originates from the Greek word ψευτικο which simply means fake.
In the case of Python in specific it relies on a function called os.urandom, which is nothing other than a software generated seed which varies based on the system implementation. So for example in Linux the algorithm will be different than Windows what both have in common is that they are all software based and predictable.
Without going into too much detail I’m going to briefly tell you how Linux and Windows implement this:
Windows: Windows relies on the CryptGenRandom function to give you the random number. This is simply an interface to the Windows Cryptographic Provider (CSP) which still relies on a software seed to be generated so by nature cannot be trusted.
Linux: In a similar way Linux provides a system call called getrandom which works by returning the randomness back to Python. It must be noted here that Linux implements this slightly different than Windows and in most studies published it produces better results than the Windows version. Having said that Windows has made a new Cryprographic API (nextgen) which is replacing the old CryptGenRandom one and is supposed to improve results. More information can be found here.
How Do You Generate a True Random Number in Python
What Are Some True Random Sources to Use for Generating Random Numbers
Lets break down some sources that one can use to start getting some good seeding for your cryptographic random generation functions.
- Sun light: Yes this is a varying source that can be used using a light sensor.
- WIFI Noise: This is another great source that you can use such as signal strength, noise ratios. The good news about this one is that you can get them from your wireless card which is almost always available these days.
- Bluetooth Signals: Similar to above but for Bluetooth
- Keyboard Input: You can have the user type random letters and use those as a seed (we will demonstrate this later)
- Keyboard Typing Speed: You can use the speed between each typing letter and use that velocity as your seed
- Temperature/Humidity/Wind: All of these are great sources but sometimes they can be predicted if the person knows the location and time that the seed got generated.
From the above the ones that are the easiest to implement are the KeyBoard Input and the Keyboard Typing Speed.
Truly Random Python Code Generation
As discussed above you need a truly random source to produce authentic random numbers in Python. We will break down some source code on how to do this using keyboard inputs and typing speed.
KeyBoard Input Random Source – Python Example
In order to detect the random keyboard input we need to do two things:
- Initialize a seed by prompting the user to type some keystrokes
- Identify these keystrokes and save them in memory or a file
For simplicity there the code below will save them in memory.
In [1]: rand_chars = input('Please input some characters: ') Please input some characters: this is a random character to be used as a seed for Unbiased Coder In [2]: rand_chars Out[2]: 'this is a random character to be used as a seed for Unbiased Coder'
As you can see above we leverage the input function to capture the data from the user. Now that we have the random characters we can save them as a seed file or in a buffer to initialize our Python Random library.
In [6]: import random In [7]: random.seed(rand_chars) In [8]: random.randbytes(10) Out[8]: b',\x97\x9e\xf9D\x03\xba\xc2\xfal'
In order to do that we just call seed and then pass it on to create a random buffer using randbytes. As it can be seen above the output now produced has the seed into effect from the random characters we previously input. The point here is that this is entirely random and cannot be predicted as I could have typed anything I wanted in the input above.
KeyBoard Typing Speed Random Source – Python Example
Similarly we can implement an algorithm for generating random source functionality for typing in a keyboard. In this case we will use a velocity value which will simply be based on the timing between the input of each character typed.
In [25]: import time In [26]: import sys In [27]: rand_chars = [] In [28]: for x in range(20): ...: before_input = time.time() ...: sys.stdin.read(1) ...: after_input = time.time() ...: rand_chars.append(after_input-before_input) ...: this is an input we are going to read from Unbiased Coder In [29]: rand_chars Out[29]: [1.9073486328125e-06, 1.1920928955078125e-06, 0.0, 0.0, 9.5367431640625e-07, 0.0, 1.1920928955078125e-06, 0.0, 7.152557373046875e-07, 0.0, 0.0, 0.0, 0.0, 10.292709112167358, 1.0013580322265625e-05, 1.1920928955078125e-06, 1.9073486328125e-06, 1.6689300537109375e-06, 1.1920928955078125e-06, 9.5367431640625e-07]
As you can see above we now have a list of timings of values that we can convert into a string or other input type so we can input to our seed function as shown in the previous example.
If we combine those two options we will improve our random seeding since we will have two sources now:
- Typing Speed on the keyboard
- Random characters given as input
How to Improve True Random Sources for Seeding
Now that we have set in stone and explained why the current Python implementation of randomness cannot be trusted or it should be used for projects that don’t rely heavily on secure randomness we can start explaining what a True Random Number is and how we can acquire one of them to use in Python.
Lets start by saying that almost all sources are predictable to some extent so there’s no golden bullet on how to accomplish this properly. There are however steps you can take to improve your chances.
- Compound multiple truly random sources together for your seed
- Take advantage of your environment
- Perform multiple iterations to acquire your seed
- Use software pseudo sources to give a boost to your algorithm
Is Python Random Number Generator Truly Random
As we discussed earlier the Python Random Number generator is not a truly random function unless there’s some extension on the system from a random source or cryptographic module.
How Do You Generate True Random Numbers
As discussed earlier you need to use a Cryptographic Module or some form of sensor that uses a true source of input. This input can then be used as a seed to your code to initialize everything in your random function generation.
Can I Generate Authentic Random Number with Python
No you cannot create authentic random numbers with Python. By default Python is bundled with a pseudo random generator which is very limited in nature and can be predicted. The sources mentioned above provide true sources of randomness and can be used as initialization for producing Authentic Random Numbers.
Conclusion
If you found How To Generate Truly Randomness In Python useful and you think it may have helped you please drop me a cheer below I would appreciate it.
If you have any questions, comments please post them below I check periodically and try to answer them in the priority they come in. Also if you have any corrections please do let me know and I’ll update the article with new updates or mistakes I did.
Which is your favorite source of randomness to use in Python?
My personal favorite is using the keyboard as it’s basically the easiest and can work everywhere. The typing speed comes from the brain and can be affected by any environmental factors.
If you would like to learn more about Python related stuff I have a few articles below: