rand_ssl - Pseudo-random number generator
#include <openssl/rand.h>
int RAND_bytes(
unsigned char *buf, int num ); int
RAND_pseudo_bytes(
unsigned char *buf, int num ); void RAND_seed(
const void *buf, int num ); void RAND_add(
const void *buf, int num, int entropy ); int
RAND_status(
void ); void RAND_screen(
void ); int RAND_load_file(
const char *file, long max_bytes ); int
RAND_write_file(
const char *file ); const char *RAND_file_name(
char *file, size_t num ); int RAND_egd(
const char *path ); void RAND_set_rand_method(
RAND_METHOD *meth ); RAND_METHOD
*RAND_get_rand_method(
void ); RAND_METHOD *RAND_SSLeay(
void ); void RAND_cleanup(
void );
These functions implement a cryptographically secure
pseudo-random number generator (PRNG). It is used by other
library functions, for example, to generate random keys.
Applications can use it when they need randomness.
A cryptographic PRNG must be seeded with unpredictable
data, such as mouse movements or keys pressed at random by
the user. This is described in RAND_add(3). Its state can
be saved in a seed file (see RAND_load_file(3)) to avoid
having to go through the seeding process whenever the
application is started.
For more information on how to obtain random data from the
PRNG, see RAND_bytes(3).
Internals [Toc] [Back]
The RAND_SSLeay() method implements a PRNG based on a
cryptographic hash function.
The following description of its design is based on the
SSLeay documentation. A good RNG includes the following
components: A good hashing algorithm to mix things up and
to convert the RNG state to random numbers. An initial
source of random state. The state should be very large.
If the RNG is used to generate 4096 bit RSA keys, two
2048-bit random strings are required (at a minimum). If
your RNG state only has 128 bits, you are limiting the
search space to 128 bits, not 2048. It should be easier
to break a cipher than guess the RNG seed data. Any RNG
seed data should influence all subsequent random numbers
generated. This implies that any random seed data entered
will have an influence on all subsequent random numbers
generated. When using data to seed the RNG state, the
data should not be extractable from the RNG state. We
believe this should be a requirement because one possible
source of secret semi-random data would be a private key
or a password. This data must not be disclosed by either
subsequent random numbers or a core dump left by a program
crash. Given the same initial state, two systems should
deviate in their RNG state (and hence the random numbers
generated) over time if at all possible. Given the random
number output stream, it should not be possible to determine
the RNG state or the next random number.
The algorithm is as follows.
There is global state made up of a 1023 byte buffer (the
state), a working hash value (md), and a counter (count).
Whenever seed data is added, it is inserted into the state
as follows:
The input is divided into blocks of 20 bytes (or less for
the last block). Each block is run through the hash function
as follows: The data passed to the hash function is
the current md, the same number of bytes from the state
(the location determined by an incremented looping index)
as the current block, the new key data block, and count
(which is incremented after each use). The result of this
is kept in md and also xored into the state at the same
locations that were used as input into the hash function.
This system addresses points 1 (hash function; currently
SHA-1), 3 (the state), 4 (via the md), and 5 (by the use
of a hash function and xor).
When bytes are extracted from the RNG, the following process
is used. For each group of 10 bytes (or less), you
do the following:
Input into the hash function the local md (which is initialized
from the global md before any bytes are generated),
the bytes that are to be overwritten by the random
bytes, and bytes from the state (incrementing looping
index). From this digest output (which is kept in md),
the top (up to) 10 bytes are returned to the caller and
the bottom 10 bytes are xored into the state.
Finally, after you finish num random bytes for the caller,
count (which is incremented) and the local and global md
are fed into the hash function and the results are kept in
the global md.
I believe the above addressed points 1 (use of SHA-1), 6
(by hashing into the 'state' the 'old' data from the
caller that is about to be overwritten) and 7 (by not
using the 10 bytes given to the caller to update the
'state', but they are used to update 'md').
Of the points raised, only the second is not addressed
(see RAND_add(3)).
Functions: BN_rand(3), RAND_add(3), RAND_load_file(3),
RAND_egd(3), RAND_bytes(3), RAND_set_rand_method(3),
RAND_cleanup(3) rand(3)
rand_ssl(3)
[ Back ] |