For The Love of Random Numbers: And A Bit of PowerShell Randomization

You wouldn’t believe the number of code reviews that I have done, where I had to point out that the keys that were being generated were not…

Photo by Guillermo Velarde on Unsplash

For The Love of Random Numbers: And A Bit of PowerShell Randomization

You wouldn’t believe the number of code reviews that I have done, where I had to point out that the keys that were being generated were not actually random and would always be created in a predictable way.

The usage of random numbers can cause many problems, as developers often just link to standard libraries which do not quite generate a proper random number, or that repeat every time they are called.

Within cryptography, random numbers are used to generate things like encryption keys. If the generation of these keys could be predicted in some way, it may be possible to guess them. The two main types of random number generators are:

  • Pseudo-Random Number Generators (PRNGs). This method repeats the random numbers after a given time (periodic). They are fast and are also deterministic, and are useful in producing a repeatable set of random numbers.
  • True Random Number Generators (TRNGs). This method generates a true random number and uses some which is random. One approach is to monitor the movements of a mouse pointer on a screen or from the pauses in key-strokes. Overall the method is generally slow, especially if it involves human interaction, but is non-deterministic and aperiodic.

Normally simulation and modelling applications use PRNG, so that the values generated can be repeated for different runs, while cryptography, lotteries, gambling and games use TRNG, as each value which is selected at random should not repeat or be predictable. Eve could thus guess the key created by the method that Bob uses to generate a key. So, in the generation of encryption keys for public-key encryption, users are typically asked to generate some random activity. The random number is then generated based on this activity.

Computer programs, though, often struggle to generate TRNG, and hardware generators are often used within highly secure applications. One method is to generate a random number based on low-level, statistically random “noise” signals. This includes things like thermal noise and the photoelectric effect.

Within cryptography, it is important that we generate values which are as near random so that Eve cannot guess the random numbers that Bob and Alice are using. With randomness, we cannot determine how random the values are by just taking a few samples. For this, we need a large number of samples and make an estimation of the overall randomness.

Monte Carlo

There are various tests for randomness. For example, we could define an average value which is halfway between the number range and then determine the ratio of the values above and below the halfway value. This will work but will not show us if the values are well distributed. Along with this we could determine the arithmetic mean of the values and match it to the centre value within the range of numbers. An improved method to test for the distribution of values is the Monte Carlo value for Pi test. With this method, we take our random numbers and scale them between 0.0 and 1.0. Next, we take two values at a time and calculate:

Sqrt(x² + y²)

If this value is less than or equal to one, we place it in the circle (with a radius of 1); otherwise, it is out of the circle. The estimation of PI is then four times the number of points in the circle (M) divided by the total number of points (N). In the figure below, the blue points are outside the circle, and the yellow ones are inside:

We thus need to test our data and see if we get a value close to PI.

Here is a sample run with 10 values [here] that are generated from random.org:

First Five Pairs:
X Y Z:
-0.671 -0.098 0.678
-0.6 -0.553 0.816
0.616 0.867 1.063
-0.678 0.09 0.684
-0.569 0.443 0.721Inval: 4 Outval: 1Result: 3.2
— — — — — — — —
Values Used: [42, 115, 51, 57, 206, 238, 41, 139, 55, 184]

A value of 3.2 is close to PI (3.14), so we have a good set of random values. If you would like to try other ones, try here.

Entropy

Another method for determining randomness is to measure the entropy of the data. It is defined by Claude E. Shannon in his 1948 paper, where the maximum entropy occurs when there is an equal distribution of all bytes across the data. Normally we define these in terms of bytes. The method we use is to take the frequencies of the byte values and calculate how many bits are at used. The maximum entropy value is 8 bits (for a byte value):

Here is the calculator is here.

Powershell Implementation

Now, let’s implement a random number generator using PowerShell. For this we will define the number of bytes that we need for the random number. With 16 bytes, we generate 128 bits as an output, and 32 bytes give us 256 bits. In the following we create a new random object ($rand), and then call the GetBytes() method, and thus put the random number in the $r variable:

$rand = [Security.Cryptography.RandomNumberGenerator]::Create()
$r = [byte[]]::new($randBytes)
$rand.GetBytes($r)

Next, we can convert this into a hex, Base64 format with the conversion methods:

"`nRandom (Hex): "+[System.Convert]::ToHexString($r)
"Random (Base64): "+[System.Convert]::ToBase64String($r)

Also, we may want to use the value as an integer. Unfortunately, our integers typically only go up to 32 or 64 bits, so we have to use a Big Integer conversion, and which converts the byte array ($r) into a Big Integer:

$val = [Numerics.BigInteger]::new($r)
"Random (Integer): "+$val

Here is the code [here]:

$randBytes=16
$randBytes = [int]$Args[0]
"Length of random number: "+$randBytes
$rand = [Security.Cryptography.RandomNumberGenerator]::Create()
$r = [byte[]]::new($randBytes)
$rand.GetBytes($r)
"`nRandom (Hex): "+[System.Convert]::ToHexString($r)
"Random (Base64): "+[System.Convert]::ToBase64String($r)
$val = [Numerics.BigInteger]::new($r)
"Random (Integer): "+$val

and a sample run [here]:

Length of random number: 16
Random (Hex): F95B121BE385D92C6E947699F50FE624
Random (Base64): +VsSG+OF2SxulHaZ9Q/mJA==
Random (Integer): 49046759820258413240911533943972584441

Conclusions

In high-risk situations, software developers really need to understand how their random number generator is working, otherwise, it might be possible to win the lottery, just by analysing the code involved.

In cryptography, we often generate encryption keys from a random number or create a nonce (a random seed for a transaction), and these numbers are not quite random, it can compromise the whole process.

Here is the code that we created:

https://asecuritysite.com/powershell/ps_rand

and some more random number examples:

https://asecuritysite.com/random/