/crude_rand_test

Crude test for crude rand() implementations

Primary LanguageCGNU General Public License v3.0GPL-3.0

crude_rand_test

Crude test for crude rand() implementations

TL;DR: Test whether the low-order bit of the value returned by C's rand() function consistently alternates between 0 and 1.

NOTE:

A previous version of this program had a serious bug; it didn't actually call rand() implementations other than the one provided by the current system. The current version displays the date when it was last updated; results from versions prior to that are invalid (other than the output for the current implementation).


ISO C specifies two functions for generating pseudo-random numbers, declared in <stdlib.h>:

void srand(unsigned int seed);

int rand(void);

You can read the description in any decent C reference, or in the standard itself, so I won't repeat it here.

The common wisdom is that rand() is not suitable for use in cryptography. For one thing, the seed is an unsigned int, which means that if unsigned int is 32 bits, there are only 232 possible sequences (and possibly only 232 possible internal states). If your system's security depends on random numbers, don't use rand().

Even worse, there are some implementations where the low-order bit of the value returned by rand() is almost completely useless; it alternates between 0 and 1. More generally, the Nth low-order bit repeats in cycle of 2N, so for example the low-order 8 bits will be exactly the same on every 8th call.

The excellent comp.lang.c FAQ mentions this in question 13.18:

Poor pseudorandom number generators (such as the ones unfortunately supplied with some systems) are not very random in the low-order bits. (In fact, for a pure linear congruential random number generator with period 2e, and this tends to be how random number generators for e-bit machines are written, the low-order n bits repeat with period 2n.) For this reason, it's preferable to use the higher-order bits: see question 13.16.

References: Knuth Sec. 3.2.1.1 pp. 12-14

In a recent discussion on the comp.lang.c newsgroup (visible here via the inexcusably clumsy Google Groups interface), I expressed skepticism that this was still an issue. After all, the sample implementation in the ISO C standard (first published in 1989) doesn't have this particular problem. I posted a small test program to test for the problem.

Ike Naar wrote that running my test program on NetBSD nb2 20110806 shows that the low-order bit does alternate between 0 and 1, and Udyant Wig posted the source code for the implementation of rand() in NetBSD's libc.

This small project is a C program that tests an implementation's rand() function for this particular issue. It doesn't perform any other tests of the quality, just whether the low-order bit consistenly alternates between 0 and 1. The program deliberately does not call srand() (not calling srand() is equivalent to calling srand() with an initial seed of 1).

The current version tests the current implementation's rand() function as well as a couple of others, compiled from source. (TODO: Add the FreeBSD version, source code here.

If anyone would care to run this on their system, particularly if it's a reasonably modern system that exhibits the problem, please send me the results and I'll publish them here (when and if I get around to it).

-- Keith Thompson <Keith.S.Thompson@gmail.com> Sat 2014-04-19