How to Generate Truly Random Numbers in POSIX Systems

Everyone knows about the rand() and srand() functions in the C Standard Library (or any of the equivalents in other programming languages). These functions work together to generate pseudo-random numbers from a seed, thus lending some nondeterminism to the program. But what about truly random numbers? What if you want a stream of random data that has no redundancy whatsoever (for statistical or scientific modeling, encryption, etc.)? For this, you will need something entirely different, and you probably won’t be able to find it in a standard library.

The generation of truly random numbers is an illusive goal. Computers and computer programs tend to be deterministic, and thus randomness is usually simulated using a pseudo-random generator (PRNG) where a randomizer is seeded with a time or timestamp. But there are ways to generate truly random numbers. These methods tend to be system-dependent (there is no cross-platform interface for truly random number generation in C at least), and they rely on environmental noise in the system for randomness rather than on anything deterministic. Hence why they are called “truly random numbers”.

Let’s say we want to generate a truly random 32-bit int value in a C program. How would we do this? I will show you a program that accomplishes this goal, using the Unix device file called /dev/random.

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <errno.h>
 5 int trand( void );
 7 int mainint argc, char **argv ){
 8         printf"%d\n", trand() );
 9         return 0;
10 }
12 // Truly random number generator
13 int trand(){
14         FILE *fp;
15         if( !(fp = fopen"/dev/random""r" ) ) ){
16                 perror"Couldn't open /dev/random" );
17                 exit( errno );
18         }
19         int i;
20         fread( &i, 41, fp );
21         fclose( fp );
22         return i;
23 }

I have made this program as simple as possible, not bothering to include anything unnecessary. All it does is generate a 4-byte random integer and print it to standard output. It does this with the trand() function, which occupies the bottom half of the program. We start with a file pointer fp and attempt to open the /dev/random file on that file pointer. If this fails we print an error message and then exit with the value of the errno variable. For more information on perror() and errno, check out my tutorial on error handling in C. If the opening was successful, the function declares an integer and then uses fread() to read four bytes of /dev/random into that integer. It then closes the file and returns the resulting integer value.

As you my have guessed, /dev/random is a character device file that generates completely random bytes when read based on environmental noise in the system. It uses various sources of randomness to derive these random bytes, including device drivers and data in the kernel. Unlike its sibling /dev/urandom, /dev/random will block if it can’t achieve the desired entropy, and so you are assured that the output will have the necessary statistical qualities of true randomness.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s