As I see it, there are two kinds of random-number generators (RNGs) needed by applications:

- Unpredictable random generators (also known as "cryptographically strong" or "cryptographically secure") are needed by some applications for data security, usually in encryption or secure communication protocols, and in some online games. The goal here is to keep the random numbers from being guessed easily.
- Statistically random generators are needed by simulations and many games to bring an element of chance and variation to the application. The goal here is for each possible outcome to be equally likely. Statistically random generators can simulate dice, playing card shuffling, etc.

The following is a sketch of a C programming interface that specifies two functions that could meet these two needs.

```
int random(byte[] bytes, size_t size);
```

Generates random bits using an unpredictable-random implementation.

**Quality**: An unpredictable-random implementation generates random bits that are unpredictable.**Predictability**: “Unpredictable” means that an outside party with knowledge of the implementation’s internal state at a certain point of time can guess neither prior unseen bits nor future bits of the random sequence correctly with more than a 50% chance per bit, even with many months of effort and even if the random algorithm used and extremely many outputs of the implementation are known.**Seeding**: If the implementation uses a deterministic algorithm to generate random numbers, its internal state must be*seeded*with unpredictable data. The internal state (the part of the algorithm’s state that can be initialized with arbitrary data) must be at least 128 bits and should be at least 238 bits (the length in bits of 54 factorial). The seed must be at least the same size as the internal state.**Reseeding**: The internal state should be reseeded from time to time to ensure each bit of the output is unpredictable even if an outside party somehow gains knowledge of its internal state.**Speed**: The implementation should select algorithms that are reasonably fast for most applications.**Time Complexity**: The implementation must run in amortized linear time on the size of the output array.**Thread Safety**: The implementation should be safe for concurrent use by multiple threads.**Examples**: The “/dev/urandom” device on many Unix-based operating systems; CryptGenRandom function on Windows; the CryptGenRandom function on Windows; cryptographic hash functions that take unpredictable signals as input (such as disk access and keystroke timings).

"bytes" is a pointer to a byte array, "size" is the number of random bytes to generate. Each bit in each byte will be randomly set to 0 or 1. Returns 0 if the function succeeds, and nonzero otherwise.

```
int random_fast(byte[] bytes, size_t size);
```

Generates random bits using a statistical-random implementation.

**Quality**: A statistical-random implementation generates random bits that, theoretically, are uniformly randomly chosen independently of the other bits. The implementation must be almost certain to pass simple statistical randomness tests and many complex ones. (For example, any RNG algorithm that passes the three test batteries in TestU01 [L’Ecuyer and Simard 2007] meets these requirements.)**Predictability**: The implementation’s output must not be trivially predictable.**Seeding**: The implementation must be seeded with information not known*a priori*by the implementation, such as random bits from an unpredictable-random implementation. As far as practical, the seed should not be trivially predictable. The internal state must be at least 64 bits and should be at least 128 bits. The seed must be at least the same size as the internal state.**Reseeding**: The implementation may reseed the internal state from time to time. It should do so if its internal state’s size is less than 238 bits. If the implementation reseeds, it should do so before it generates more values than the square root of the RNG’s period.**Speed**: The implementation should select algorithms that are reasonably fast for most applications. The implementation may instead use an unpredictable-random implementation as long as the function remains at least as fast, in the average case, as the statistical-random implementation it would otherwise use.**Time Complexity**: The implementation must run in amortized linear time on the size of the output array.**Thread Safety**: The implementation should be safe for concurrent use by multiple threads.**Examples**: The “xorshift128+” and Lehmer128 random number generators.

"bytes" is a pointer to a byte array, "size" is the number of random bytes to generate. Each bit in each byte will be randomly set to 0 or 1. Returns 0 if the function succeeds, and nonzero otherwise.

## Shuffling

A deterministic random number generator (DRNG) can’t generate more permutations of random number sequences than its period. A DRNG can’t generate all permutations of a list if the factorial of its size is greater than the DRNG’s period. This means that the items in a shuffled list of that size will never appear in certain orders when that DRNG is used to shuffle it.

A DRNG with period 2^{64}, for example, can’t generate all permutations of a list with more than 20 items; with period 2^{128}, more than 34 items; with period 2^{226}, more than 52 items; and with period 2^{256}, more than 57 items.

When shuffling more than 20 items, a concerned application would be well advised to use an unpredictable-random implementation.

## Seedable Random Generators

In addition, some applications generate results based on apparently-random principles, starting from a known initial state. One notable example is a “code”, or password, for generating a particular game level in some role-playing games.

Functions for seeding random number algorithms are not included, because applications that require seeding usually care about reproducible results. Such applications often need to keep not only the RNG algorithm stable, but also any algorithm that uses that RNG algorithm (such as a game level generator), especially if it publishes seeds (for example, game level passwords). Moreover, which RNG algorithm to use for such purpose depends on the application. But here are some recommendations:

- Any RNG algorithm selected for producing reproducible results should meet at least the quality and predictability requirements of a statistical-random implementation, and should be reasonably fast.
- Any seed passed as input to that algorithm should be 64 bits or greater.

An application should only use seeding if–

- the initial state (the seed) which the “random” result will be generated from is known (for example, because it’s hard-coded or because it was entered by the user),
- the application needs to generate the same “random” result multiple times,
- it would be impractical to convey that “random” result without relying on seeding, such as–
- by saving the result to a file, or
- by distributing the results or the random numbers to networked users as they are generated, and

- the RNG algorithm and any procedure using that algorithm to generate that “random” result will remain stable as long as the relevant feature is still in use by the application. (Not using seeding allows either to be changed or improved without affecting the application’s functionality.)