Click here to Skip to main content
Email Password   helpLost your password?

Random numbers should not be generated
with a method chosen at random

- Donald Knuth
The Art of Computer Programming
Volume II: Seminumerical Algorithms

Introduction

Random numbers are a primitive element not only to cryptographers, but Computer Scientist and Programmers in general. What is desired is a method which produces a pseudo random stream of numbers fast which are cryptographically secure. However, the goals are diametrically opposed - pseudo random sequences can be produced quickly, or can be produced strongly; but usually not quickly with properties which resist Cryptanalysis.

This article will examine the applications of Pseudo Random Number Generators. Topics covered will include:

Downloads

There are seven downloads available with this article. The downloads are presented at the end of the article.

Usefulness of Random Numbers

In his prolific work The Art of Computer Programming, Volume II: Seminumerical Algorithms, Donald Knuth identifies the following common situations in which one may require random numbers:

Simulation and sampling are self explanatory. Numerical Analysis uses random numbers to solve complicated problems. For example, a Predator/Prey model using differential equations. Four is equally obvious. Taking from Knuth on item five, Decision Making:

There are reports that many executives make their decisions by flipping a coin or by throwing darts, etc. It is also rumored that some college professors prepare their grades on such a basis. Sometimes it is important to make a completely "unbiased" decision. Randomness is also an essential part of optimal strategies in the theory of matrix games.

The human ear can distinguish between synthesized music (generated from a computer) versus that of an artist. The artist will have small deviations in rhythm which makes the music more pleasing. Additionally, a small bit of randomness makes computer generated graphics appear softer. Note the rigid structure below of the left image versus the softness of the right image. Below the right image was produced with a filter which added a small random amount noise. In Signal Processing, this is known as Anti-Aliasing.

No Random Noise

Random Noise

To further impress aesthetics upon the reader, Adobe Photoshop employs random numbers in many of its filters, including Blur, Distort, and Noise.

Adobe Photoshop Filters

Finally, recreation would include shuffling cards or rolling dice.

Random Number Generator Classes

Taking frm NIST, FIPS 140-2:

Random Number Generators fall into one of two classes: deterministic and nondeterministic. A deterministic RNG consists of an algorithm that produces a sequence of bits from an initial value called a seed. A nondeterministic RNG produces output that is dependent on some unpredictable physical source that is outside human control.

Note that layman generally refer to the nondeterministic generator as a 'true random number generator'.

Types of Random Number Generators

There are two types of deterministic random number generartors from which a programmer may choose:

Pseudo Random Number Generators would include generators such as Linear Congruential Generators and Mersenne Twisters. They are generally good at quickly providing a uniformly distributed stream over the interval [0, 1). They offer little to no cryptographic security.

Cryptographically Secure Pseudo Random Number Generators have additional properties which make them suitable for use in Cryptography. Cryptographic uses would include:

A Nonce is a number or bit string used only once. It is a pseudo random number issued in an authentication protocol to ensure that old communications cannot be reused in replay attacks. To ensure that a nonce is used only once, it should be time-variant (including a suitably granular timestamp in its value), or generated with enough random bits to ensure a probabilistically insignificant chance of repeating a previously generated value.

The One Time Pad (invented circa 1917) is an encryption algorithm where the plaintext is combined with a random key or "pad" that is as long as the plaintext and used only once. A modular addition is used to combine the plaintext with the pad. For binary data, the operation XOR amounts is the equivalent. If the key is truly random, never reused, and kept secret, the one time pad provides perfect secrecy.

Random Number Sources

Though NIST does not currently recognize any nondeterministic RNGs, one may use a deterministic RNG to seed a cryptographically secure pseudo random number generator. Taking from FIPS 140-2:

Until such time as an Approved nondeterministic RNG standard exists, nondeterministic RNGs approved for use in classified applications may be used for key generation or to seed Approved deterministic RNGs used in key generation

NIST provides tests which allows one to develop heuristics for determining the of the quality of the sequence from the generator inquestion. Included for download are NIST Validation Suite, FIPS 140-2, and and FIPS 186. Additionally, the reader may want to examine ANSI 9.17, Appendix C (Approved Random Number Generators for FIPS 140-2, Security Requirements for Cryptographic Modules).

Also of interset is NIST SP800-90, Recommendation for Random Number Generation Using Deterministic Random Bit Generators. Some conservative cryptographers do not recommend using Dual_EC-DRBG (the elliptic curve variant) but does recommend using CTR_DRBG or Hash_DRBG. Schneier's article can be found at Did NSA Put a Secret Backdoor in New Encryption Standard?

Background on Tests

In a random sequence, on would expect each of the ten decimal digits to occur approximately 1/10 times. Should the radix be 2 (digits of either 0 or 1), each digit should represent approximately 50% of the sequence.

Testing involves differentiating good sources from poor choices. For example, the binary stream ...1111111110000000000... would perform ideally with a simple Frequency test, but fail at advanced tests such as Runs, Longest Runs in a Block, and Cumulative Sums. A counter intuitive point with the presented binary stream is that it is a valid sequence of random numbers. Each stream is as equally likely to occur as any other in an unbiased generator.

Testing Sequences

Below the reader will find various tests which should be used when evaluating the effectiveness of a generator. The reader should refer to NIST's Guide to the Statistical Tests and Knuth's The Art of Computer Programming for a complete description.

In addition, NIST's SP800-22, A Statistical Test Suite for Random and Pseudorandom Number Generators for Cryptographic Applications should be consulted. NIST's site includes software for testing the generator.

NIST requires a PRNG pass 16 statistical tests. The tests are listed below with a brief description.

Knuth sates a random sequence should pass 13 statistical tests. Tests which are not included in NIST's requirements are listed below.

Seeding

Cryptographically Secure RNGs share an Achilles' heel with the other pseudo random number generators - both require an starting seed as an input. Should the secret seed become compromised, an adversary can generate the entire output sequence instantly by using the same algorithm.

In 1995 David Wagner, then a graduate student at Berkeley, and fellow student Ian Goldberg cracked the random number generator used by the Netscape web browser to secure online transactions. The pair determined that Netscape was constructing its seeds using easily predicted numbers, such as the time of day.

Key Derivation Functions

Key derivation functions are used (among others) to derive keys from secret passwords or passphrases. For guidance one can use RFC 2898, Password-Based Cryptography Specification. In addition, the .NET platform provides Rfc2898DeriveBytes, which is part of System.Security.Cryptography.

Key derivation functions are often used in conjunction with non-secret parameters to derive a keys from a common secret value. A KDF may also be used to ensure that derived keys have other desirable properties, such as avoiding weak keys in some specific encryption systems.

Key derivation functions are also used in applications to derive keys from secret passwords or passphrases, which typically do not have the desired properties to be used directly as cryptographic keys. In such applications, it is generally recommended that the key derivation function be made deliberately slow so as to frustrate brute force attack or dictionary attack on the password or passphrase input value.

Such use may be expressed as Dk = KDF(Key, Salt, Iterations) where Dk is the derived key, KDF is the key derivation function, Key is the original key or password, Salt is a random number which acts as cryptographic salt, and Iterations refers to the number of iterations of a sub-function. The derived key is used instead of the original key or password as the key to the system. The values of the salt and the number of iterations (if it isn't fixed) are stored with the hashed password or sent as plaintext with an encrypted message.

Standard C++ rand( ) Function

The Standard C++ rand() function uses a linear congruential generator. It offers a uniformly distributed bit stream quickly when the parameters m, a, c, and X0 are appropriately chosen. The LCG offers no Cryptographic Security.

X0 is colloquially referred to as the seed, often using the system time. The generator obtains numbers by using the following recurrence relation:

Xn+1 = (aXn + c) mod m

The values chosen for the generator in Microsoft's Visual C++ environment are shown below. Note that the & 0x7FFF is performing the modular reduction.

return (((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);

Joan Boyar's PhD dissertation, Inferring Sequences Produced by a Linear Congruential Generator Missing low-order Bits is an interesting read. The astute reader should realize there probably exists an online gaming site using an insecure system. Note that this is a different attack than Wonging (named after Stanford Wong, a former IBM researcher and professional gambler), which is basically a card counting system.

Minimal Standard Generator

First proposed by Miller, Lewis, and Goldman in 1969, this generator is is a linear congruential generator with c=0. The refinement of dropping the constant resulted in a Multiplcative Generator:

Xn+1 = aXn mod m

Park and Miller suggest the values of a = 75 = 16807, m = 231-1 = 2147483647. 231-1 produces a period of 231-2. Other valuse of a exist when using 231-1: 48271 and 69627. No other values should be used.

Non Linear Congruential Generator

There are many fast random number generators available for use as a replacement to the standard C/C++ library's rand() and srand() funtions. The reader should familiarize themselves with Random Number Generators: Good Ones Are Hard To Find. Steve Park provides the source code to the Lehmer generator at his Random Number Generator webpage. Park's code provides additional PRNGs based on the following distributions (these generators are referred to as Non Linear Congruential Generators):

A Mersenne Twister, developed in 1997 by Makoto Matsumoto and Takuji Nishimura would also fall under this category. An interesting factiod in the world of computer viruses is that 30 viruses use the generator. It is speculated one author is responsible for these viruses.

Win32 API CryptGenRandom( )

CryptGenRandom() generates a requested number of bytes for the user. GenCryptRandom() is an excellent source of entropy on Windows since it is available for all Operating Systems except NT 3.51 and earlier, and Windows 95 (SR1) and earlier.

The latest seed value for CryptGenRandom is stored in the Windows Registry under the key \SOFTWARE\Microsoft\Cryptography\RNG\Seed of the HKEY_LOCAL_MACHINE hive. The seed is developed by the Operating Systems using various system parameters. For example, on a Windows CE device, the following will be used:

After the seed is developed, it undergoes two cryptographic transforms: an MD4 hash and a RC4 encryption for additional mixing and chopping.

Sample 1 demonstrates using the Windows API to acquire pseudo random values. To remove the burden of an SDK, the program uses LoadLibrary() and GetProcAddress().

Compiling and Integrating Crypto++

Crypto++Please see the related article, Compiling and Integrating Crypto++ into the Microsoft Visual C++ Environment. This article is based upon basic assumptions presented in the previously mentioned article. It also addresses most problems encountered with projects from Command Line to MFC (Errors C1083, C1189, LNK1104, LNK2001, and LNK2005). Additionally, it provides some tips and other niceties for using the Crypto++ Library.

LC_RNG

LC_RNG is a Linear Congruential RNG. Though this generator has no cryptographic value, it does allow one to reproduce results when debugging a program. Additionally, it is generally faster at generating a byte block (or stream). If one seeds the LCG with 0x00, a steady stream of 0x80 is the result. This seed value produces a period of 1. Other seeds perform as desired. Sample 1 may be used to compare the results of various seed values of Linear Congruential Generators.

RandomPool

The RandomPool behaves similar to an LCG in that the same seed produces the same results. However, unlike LC_RNG, the cipher behind the RandomPool is currently MD5<SHA>. randpoool.cpp provides typedef MDC<SHA> RandomPoolCipher. Then RandomPool would be initialized and used as follows (as demonstrated in Sample 3):

// Must be at least 16 for RandomPool
const unsigned int SEEDSIZE = 16;
byte pcbSeed[ SEEDSIZE ];

// Scratch Area
const unsigned int BLOCKSIZE = 16 * 8;
byte pcbScratch[ BLOCKSIZE ];

...

// Random Pool Initialization
CryptoPP::RandomPool rng( SEEDSIZE );
rng.Put( pcbSeed, SEEDSIZE );

// Use
rng.GenerateBlock( pcbScratch, BLOCKSIZE );

AutoSeededRandomPool

An auto seeded random pool was suggested by Leonard Janke, which Wei Dai later incorporated into Crypto++. AutoSeededRandomPool uses the RandPool design from PGP. It is suitable for all cryptographic purposes including generating keys and IVs. Depending on the Operating System, the generator will be seeded using the following:

Sample 4 trivially demonstrates using an AutoSeedeRandomPool.

// Scratch Area
const unsigned int BLOCKSIZE = 16 * 8;
byte pcbScratch[ BLOCKSIZE ];

// Construction
AutoSeededRandomPool rng;

// Random Block
rng.GenerateBlock( pcbScratch, BLOCKSIZE );

AutoSeededX917RNG

Unlike LG_RNG and RandomPool, AutoSeededX917RNG does not require seeding. However, one must specify an approved Block Cipher as a template parameter. The two ANSI 9.17 approved ciphers are 3-key Triple DES and SHA1. Sample 5 demonstrates use with SHA1.

// Scratch Area
const unsigned int BLOCKSIZE = 16 * 8;
byte pcbScratch[ BLOCKSIZE ];

// Construction
AutoSeededX917RNG< DES_EDE3 > rng;

// Random Block
rng.GenerateBlock( pcbScratch, BLOCKSIZE );

Application Table

The following table should be applied when chosing a Random Number Generator in practice.

Additional CSPRNGs

In addition to the previously mentioned, various FIPS standards recognizes other cryptographically secure generators. As the reader should now realize, a Cryptographically Secure Pseudo Random Number Generator wraps a deterministic generator in a difficult problem. FIPS 186-3 approves the Digital Signature Algorithm (DSA) and Elliptic Curve DSA (ECDSA) as CSPRNGs.

Poor Generators

This section is included for pandectic resaons. I hope the reader will appreciate (and sometimes enjoy) the shortcomings.

Middle Square Method

The Middle Square Method of generation was proposed by John von Nuemann. The generator was used from 1946 to the mid 1950s. Keep in mind that in 1946, the computer was 1 year old. The generator suffered from the fact it converged to a sequence of 0s too quickly; and once at 0, it was latched at 0.

IBM Mainframe RANDU

RANDU was a congruential generator supplied by IBM for use on it's mainfame computers. The choice of a=65539 and m=231 proved to be a poor choice. When the authors of Numerical Recipies in C generated a sample and plotted the planes, only 11 planes existed (where there should have been on the order of m1/k, where k is the number of random numbers chosen plotted in three dimensional space. The generator suffered from Correlation in k-space. The IBM representative stated:

We guarantee that each number is random individually, but we don't guarantee that more than one of them is random.

Subtract with Borrow

In 1992, physicists discovered that even "high-quality" random-number generators, can yield incorrect results under certain circumstances. In preparation for simulating the three-dimensional Ising model, researchers tested the package on the two-dimensional version, which has a known answer. The result was incorrect. [1]

Summary

This article presented the reader with with various choices for a pseudo random number generator based on the problem domain. Should the reader require a source for Simulation or Sampling, choose an LCG. If the reader requires strength, choose the Win32 API, AutoSeededRandomPool, or AutoSeededX917RNG. If the reader requires Cryptographic Security, choose an AutoSeededX917. And finally, if the reader requires entropy, use Win32 API or AutoSeededRandomPool.

In addition, other generators exist (some of which are exposed in Crypto++). For example, the Blum Blum Shub CSPRNG produces a bit sequence based on Quadratic Residues. The generator will remain cryptographically secure as long as Integer Factorization remains hard. It has yet to be determined where Integer Factorization lies in Complexity Theory.

Acknowledgements

Revisions

Downloads

Checksums

References

[1] The Bias of Random-Number Generators, http://www.sciencenews.org/articles/20030927/mathtrek.as, accessed November 2007.

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralCan you help me to use CCrypto ?
mesajflaviu
23:26 13 May '09  
Hello . I saw that you work with CCrypto from Dave Kerr A simple MFC class to encrypt data with the Crypto API[^]... and I want to use this class into MDI project , where should I put this code to function it ?

// Now I want to encrypt my applications document object.
CDocument* pDoc = GetDocument();

if(crypto.Encrypt(*pDoc, arBytes) == true)
{
// Store the byte array in a file, the registry, whatever.
}

Can you help me ? Thanks !!
GeneralNice Article!
Dlt75
5:38 15 Apr '09  
You did a very clear and good job with this article.
Thank you for the contribute! Smile
Generalthat's good thank you very much!
khalid altahree
4:54 25 Mar '09  
I'm looking for program using c#
to solve eqoutions in numerical system
I'm from yemen sothat I'm very sorry if I can't write in english very well
Generaldistribution of hits
libatech
4:11 30 Jun '08  
Hi. your sentence "In a random sequence, on would expect each of the ten decimal digits to occur approximately 1/10 times" triggered my attention. If you look at the distribution of HITS on a uniform field, you will see that it is not uniform as you suspect, but poisson.
i.e., about 1/3 of the numbers are chosen once, about 1/3 are not chosen at all, and the other 1/3 looks geometrically distributed (but don't catch me on that last one, since i say it just from sight).
I know it might sound couter-intuitive but it's true.
GeneralAnother great article!
Sam Levy
13:03 10 Apr '08  
Thanks, keep it up.

I would really love to see a survey article on the currently available crypto packages for the Windows environment, if you have any spare time...
GeneralI need help
Member 4174639
10:03 27 Mar '08  
Hi all,
i created a sample console application in win32 in VS 2005.I want to run
this application for PocketPc.
So i chaged the Platform in project properties.
I am getting
" fatal error C1189: #error : Must define a target architecture."
GeneralRe: I need help
Jeffrey Walton
10:37 27 Mar '08  
Hi Member,

I have never tried to use Crypto++ on a Pocket PC (my 3150 battery is dead, so it is collecting dust).

MSDN: C1189[^].

Windows CE Port: Windows CE Port[^].

Jeff
GeneralWeaknesses in Windows CryptoAPI random number generator
ChrisGh
10:42 14 Feb '08  
Hi!

First, thanks for the nice article! Could you please comment as a crypto expert on the weaknesses reported in the Microsoft CryptoAPI random number generator on Windows 2000 and Windows XP reported by Heise security?

You can find the two (English) articles here:

Weaknesses in the Windows 2000 random number generator

Windows XP random number generator flawed

The first article links to a PDF of the research paper describing the weakness.

Is it still safe enough to use CryptoAPI to generate e.g. the Salt value for an AES encryption?

Thanks!

Christian
GeneralRe: Weaknesses in Windows CryptoAPI random number generator
Jeffrey Walton
11:34 14 Feb '08  
Hi Christian,

ChrisGh wrote:
Could you please comment as a crypto expert

Sadly, I cannot. I don't consider myself an expert. From the article, if the attacker does not have access to the physical machine, you are still probably safe.

I personally use Crypto++ X9.17 PRNG when I need a secure value. The seed is drawn from the Windows CryptoAPI, but the values are derived from 3DES. So your attacker would need access to your physical machine to compromise state, then unwind a block cipher to predict values.

Jeff
Generalpedantic reasons
rfmobile
7:19 30 Nov '07  
Spellcheck my friend ... (or maybe this is a sly joke) Smile

"This section is included for pendactic resaons. I hope the reader will appreciate (and sometimes enjoy) the shortcomings."

(That's ok. I kant spel ither.)

Typos aside - great article. Keep up the good work.
GeneralRe: pedantic reasons
Jeffrey Walton
7:31 30 Nov '07  
rfmobile wrote:
Spellcheck my friend ... (or maybe this is a sly joke)

No... Another fat finger on my part. I did ask Chris to include a spell checker module on the web submit tool.= (this was about a week ago).

Jeff


GeneralBoost.Random
Stephen Hewitt
19:51 17 Sep '07  
Boost's[^] Random Number Library[^] may (or may not) interest you.


Steve

GeneralRe: Boost.Random
Jeffrey Walton
9:21 18 Sep '07  
Hi Steve,

If you put together a small blurb, I'll be happy to add it to the article. I personally have never used Boost.

Jeff

GeneralDid you have any suggestions how to use NIST Validation Suite.thanks
bygreencn
18:38 12 Sep '07  
Smile
I download the NIST Validation Suite,but i have not make it work,Did you have any suggestions how to use NIST Validation Suite.
thanks a lot!!

bygreencn@gmail.com
GeneralRe: Did you have any suggestions how to use NIST Validation Suite.thanks
Jeffrey Walton
8:31 13 Sep '07  
Hi,

I have never built my own generator. Sorry.

Jeff
Generalgood artical
twzhen
22:05 11 Sep '07  
It is good Artical.

May I use it?
GeneralRe: good artical
Jeffrey Walton
10:23 13 Sep '07  
Hi,

twzhen wrote:
May I use it?

It is on the web (public domain), so cite your source. It is not nice to plagerize.

Jeff



GeneralRe: good artical
twzhen
18:00 13 Sep '07  
Hi,
Jeff,I think you may make some mistakes. What I have said "May I use it" Just for study, not have any interest for me.
And I not to going to plagerize.

Again, thanks for your article,^_^

GeneralRe: good artical
Jeffrey Walton
19:25 13 Sep '07  
twzhen wrote:
What I have said "May I use it" Just for study, not have any interest for me.


Of course...
GeneralNo comment on VBScript's random?
Chris Maunder
4:10 28 Aug '07  
I've seen some poor results with this one but never got around to actually analysing it. I'd be interested (in a purely academic way)

cheers,
Chris Maunder
CodeProject.com : C++ MVP

GeneralRe: No comment on VBScript's random?
David Scambler
12:19 12 Nov '07  
Chris,
see this article: http://www.rlmueller.net/RndFunction.htm

Anyone serious about random numbers should never use an LCG.
GeneralMulti machines
WalderMort
5:58 18 Aug '07  
Hey Jeff,

I'm developing a multiplayer game engine to be used across networks. Each game could have up to 4 PC's connected. Now to cut down on the networking load, I have decided that each machine is to the the bulk of the work. Each machine would have a random number generator each of which is supplied with an identical seed. From experience, I know that using the same seed results in the same set of 'random' numbers. I'm hoping this will remain true on each machine.

My concern here is with all the different CPU's floating around now. Am I right to presume the same sequence would be generated on any machine, providing of course the same formula and seed were used?

Here is the class I am using:
cRand::cRand( unsigned long seed ) 
{
RandomInit(seed);
}

// returns a random number between 0 and 1:
double cRand::DRandom()
{
long double c;
c = (long double)2111111111.0 * x[3] +
1492.0 * (x[3] = x[2]) +
1776.0 * (x[2] = x[1]) +
5115.0 * (x[1] = x[0]) +
x[4];
x[4] = floorl(c);
x[0] = c - x[4];
x[4] = x[4] * (1./(65536.*65536.));
return x[0];
}

// returns integer random number in desired interval:
int cRand::IRandom(int min, int max)
{
int iinterval = max - min + 1;
if (iinterval <= 0)
return 0x80000000; // error
int i = int(iinterval * DRandom()); // truncate
if (i >= iinterval)
i = iinterval-1;
return min + i;
}

// this function initializes the random number generator:
void cRand::RandomInit (unsigned long seed)
{
int i;
unsigned long s = seed;
// make random numbers and put them into the buffer
for (i=0; i<5; i++) {
s = s * 29943829 - 1;
x[i] = s * (1./(65536.*65536.));
}
// randomize some more
for (i=0; i<19; i++) DRandom();
}

GeneralMy Project work is related to Cryptography API ?
23:57 12 Feb '07  
SmileSo, Can You please tell, How would i getting start to get the good stuf and programming skills on Crypto API technology. please give suggesstion to me.

regards,
Rammy.

Rammy
GeneralRe: My Project work is related to Cryptography API ?
Jeffrey Walton
0:10 13 Feb '07  
Hi Rammy,

A college level Cryptograhy class is probably the best place to get the underlying theory. Along the way, you'll definetly pick up what system (Signatures versus PKI, etc) to use for a problem domain.

MSDN is a good start for the API. Keith Brown has a few nice books on Securty and Windows in general from the programming side (I have one of his earlier books). See Programming Windows Security[^] and
The .NET Developer's Guide to Windows Security [^]

Jeff

GeneralThe purpose of this test is to
labreuer
4:57 16 Jan '07  
Under "Testing Sequences", you repeat the text "The purpose of this test is to" for each bullet -- I suggest deleting it to make the section more readable.


Last Updated 10 Apr 2008 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010