Random Entropy in Bash

When using random numbers in Bash, the question of random entropy will sooner or later come up. This article will help you understand what entropy is, how it can be modified and optimized in Bash, and how it will affect random number generation.

In this tutorial you will learn:

  • How to generate random entropy in Bash
  • How to pre-seed the random number generator in Bash
  • Examples demonstrating random entropy generation in Bash

Random Entropy in Bash

Random Entropy in Bash

Software requirements and conventions used

Software Requirements and Linux Command Line Conventions
Category Requirements, Conventions or Software Version Used
System Linux Distribution-independent
Software Bash command line, Linux based system
Conventions # – requires linux-commands to be executed with root privileges either directly as a root user or by use of sudo command
$ – requires linux-commands to be executed as a regular non-privileged user

Example 1: Random, or not so random?

We can easily generate a random number in Bash:

$ echo $RANDOM
13


However, whilst this number looks random, it is in fact not, or at best pseudo-random. This is because a computer can in and by itself never be truly random, and the random number generator in Bash is pre-seeded with a value, which determines all subsequent calls of the $RANDOM variable/function.

Let’s pre-seed the random number generator in a few different ways. We’ll start off by pre-seeding the random generator with seed ‘1’ by setting RANDOM to 1:

$ echo $RANDOM
25552
$ RANDOM=1  
$ echo $RANDOM
16807
$ RANDOM=1
$ echo $RANDOM
16807  
$ echo $RANDOM
15089
$ RANDOM=1
$ echo $RANDOM
16807  
$ echo $RANDOM
15089
$ RANDOM=a
$ echo $RANDOM
20034

Note that the 16807 and secondary-call 15089 results remain the same while the random generator was pre-seeded with 1. It changes when pre-seeded with a.

Whilst the $RANDOM variable in Bash will always yield a random number generated by the Bash random number generator, it is also a variable which, when set, pre-seeds the random generator. The challenge is that if the seed is the same, the outcome (and sequence!) will also be the same, as you can see from studying the above example.

How the random generator is initialized in your system may depend on the Linux or Unix operating system in use, hardware used, and configuration settings. Let’s immediately agree it is not a very secure way to generate a true/real random number, hence the terms pseudo-random and pseudo-randomness. That said, much can be done to make it (much) better.

Example 2: Our own random entropy generator

The only input which is available to the random generator is basically the seed as passed to RANDOM=. So how can we come up with a truly random seed to seed the random generator, and create real random entropy (entropy: the quality of lack of predictability)? Random entropy is important, especially in the field of computer security.

Think about this question; how can you provide (to Bash) the most random input to use as a seed for random entropy generation?

I believe I have found a solution in the following code:



$ date +%s%N
1593785871313595555
#        |--------| < Selected part indicated
$ date +%s%N | cut -b10-19
4418322030
$ date +%s%N | cut -b10-19
4914627208
$ date +%s%N | cut -b10-19
5282934388
$ date +%s%N | cut -b10-19
5635463163
$ date +%s%N | cut -b10-19
5967700148
$ date +%s%N | cut -b10-19
6322917009
$ RANDOM=$(date +%s%N | cut -b10-19)
$ echo $RANDOM
16349
$ RANDOM=$(date +%s%N | cut -b10-19)
$ echo $RANDOM
9713

The final 9713 result is almost truly random.

date +%s%N is a combination of %s which is the seconds since 1970-01-01 00:00:00 UTC – quite a unique number, but still something which could potentially be re-calculated. And %N is nanoseconds. Then we slice the input to grab only the last 10 digits.

This means we are passing the second (last 0-9 digit) + the full exact nanosecond 000000000-999999999 to the random generator as a seed. This would be as good as impossible to reconstruct, unless you capture the value generated before assigning it. Almost truly random.

This also means you can get a semi-random number of x digits by simply selecting the most granular part of the microsecond:

date +%s%N | cut -b19-19
date +%s%N | cut -b18-19
date +%s%N | cut -b17-19

The first command will produce 1 digit, the second 2 digits etc.

However, the longer your cut slice becomes (by increasing the cut length), the less pseudo-random the number will be, especially once you slice into the seconds part. You could also leave off the %s, and reduce the cut size to have a less intensive system call. Whilst it may not matter for a single call of $RANDOM, it would matter if it was called hundreds of thousands of times.

Conclusion

In this article, we saw how to generate random entropy, in a reasonably random way. Whilst no random entropy generator is perfect (and therefore any random number resulting from it), we came close by calling on nanosecond time. We also saw how pre-seeding the random generator entropy variable with a specific seed will subsequently yield the same outcomes whenever a random number is generated using the $RANDOM variable.

Update your scripts with our random entropy initializer, or let us know if you discovered a better one in the comments below. Who else is interested in better entropy?!

Enjoy!



Comments and Discussions
Linux Forum