You want to use a library-level interface to EGADS for gathering entropy or getting cryptographically strong pseudo-random data. For example, you may need entropy on a system such as Microsoft Windows, where there is no built-in API for getting it.
Use the EGADS API as described in the following Section 11.8.3.
EGADS, the Entropy Gathering and Distribution System, is capable of performing many functions related to random numbers. First, it provides a high-level interface for getting random values, such as integers, numbers in a particular range, and so on. Second, EGADS does its own entropy collection, and has a library-level API for accessing the collector, making it a simple API to use for any of your randomness needs.
EGADS supports a variety of Unix variants, including Darwin, FreeBSD, Linux, OpenBSD, and Solaris. In addition, it supports Windows NT 4.0, Windows 2000, and Windows XP. Unfortunately, EGADS does not support Windows 95, Windows 98, or Windows ME because it runs as a service (which is a subsystem that does not exist on these versions of Windows). EGADS is available from http://www.securesoftware.com/egads.
EGADS is a good solution for the security-minded because it is conservative. It contains a conservative entropy collector and a conservative pseudo-random number generator. Both of these components have provable security properties that rely only on the strength of the AES cryptographic algorithm. EGADS does a good job of protecting against compromised entropy sources, which other PRNGs tend not to do. It also provides a good amount of protection against backtracking attacks, meaning that if the internal generator state does get compromised, few if any of the previous generator outputs will be recoverable.
To use EGADS, you must install the package, start up the server that comes with it, include egads.h, and link against the correct library, which will typically be libegads.so on Unix (libegads.dyld on Darwin) and egads.lib on Windows.
Before you can use any of the functions in the EGADS package, you
must first initialize a PRNG context by calling egads_init(
)
:
void egads_init(prngctx_t *ctx, char *sockname, char *rfile, int *err);
This function has the following arguments:
ctx
PRNG context object that is to be initialized. The caller should allocate the object either statically or dynamically.
sockname
If not specified as NULL
, this is the address of
the server. On Unix, this is the name of the Unix domain socket
created by the EGADS server. On Windows, this is the name of the
mailslot object created by the EGADS service. If specified as
NULL
, which is normally how it should be
specified, the compiled-in default will be used.
rfile
Name of a file from which entropy can be read. On Unix, this defaults
to /dev/random if it is specified as
NULL
. This argument is always ignored on Windows.
err
If any error occurs, an error code will be stored in this argument. A
value of 0 indicates that no error occurred; otherwise, one of the
RERR_*
constants defined in
egads.h will be returned.
NULL
may not be specified here.
The function egads_entropy( )
establishes a
connection to the entropy gateway and obtains the requested number of
bytes of raw entropy. If not enough entropy is currently available to
satisfy the request, this function will block until there is. Its
signature nearly matches that of spc_entropy( )
from Recipe 11.2:
void egads_entropy(prngctx_t *ctx, char *buf, int nbytes, int *err);
This function has the following arguments:
ctx
PRNG context object that has been initialized.
out
Buffer into which the entropy data will be placed.
nbytes
Number of bytes of entropy that should be written into the output buffer. You must be sure that the output buffer is sufficiently large to hold the requested data.
err
If any error occurs, an error code will be stored in this argument. A
value of 0 indicates that no error occurred; otherwise, one of the
RERR_*
constants defined in
egads.h will be returned.
NULL
may be not be specified here.
The function PRNG_output(
)
allows you to get byte strings of cryptographically random data. Its
signature nearly matches that of spc_rand( )
from
Recipe 11.2:
void PRNG_output(prng_ctx *ctx, char *buf, int64 nbytes);
This function has the following arguments:
ctx
PRNG context object that has been initialized.
buf
Buffer into which the entropy data will be placed.
nbytes
Number of bytes of random data that should be written into the output buffer. You must be sure that the output buffer is sufficiently large to hold the requested data.
The function egads_destroy(
)
resets a PRNG context object. Before the memory for the context
object is freed or goes out of scope (because it is statically
allocated on the stack), egads_destroy( )
must be
called on a successfully initialized context object. This ensures
that the connection to the EGADS server or service is broken, and
that any other memory or state maintained by EGADS that is associated
with the context object is cleaned up.
void egads_destroy(prngctx_t *ctx);
This ctx
argument is the successfully initialized
PRNG context that is to be destroyed. It is the
caller's responsibility to free any memory used to
allocate the object
The rest of the EGADS API allows you to retrieve pseudo-random values of particular data types. All functions in this API take a final argument that, on completion of the call, contains the success or failure status. On failure, the error argument contains an integer error code. On success, it will be 0.
void egads_randlong(prngctx_t *ctx, long *out, int *error); void egads_randulong(prngctx_t *ctx, unsigned long *out, int *error); void egads_randint(prngctx_t *ctx, int *out, int *error); void egads_randuint(prngctx_t *ctx, unsigned int *out, int *error); void egads_randrange(prngctx_t *ctx, int *out, int min, int max, int *error);
The egads_randlong(
)
function gets a pseudo-random long value,
whereas egads_randulong(
)
gets a pseudo-random unsigned long value from
to ULONG_MAX
inclusive. The functions
egads_randint( )
and egads_randuint(
)
do the same things, but on integer types
instead of longs. To get a random integer in a specified range, use
the function egads_randrange(
)
. The min
and
max
arguments are both inclusive, meaning that
they are both values that can possibly be returned.
void egads_randreal(prngctx_t * ctx, double *out, int *error); void egads_randuniform(prngctx_t *ctx, double *out, double min, double max, int *error); void egads_gauss(prngctx_t *ctx, double *out, double mu, double sigma, int *error); void egads_normalvariate(prngctx_t *ctx, double *out, double mu, double sigma, int *error); void egads_lognormalvariate(prngctx_t *ctx, double *out, double mu, double sigma, int *error); void egads_paretovariate(prngctx_t *ctx, double *out, double alpha, int *error); void egads_weibullvariate(prngctx_t *ctx, double *out, double alpha, double beta, int *error); void egads_expovariate(prngctx_t *ctx, double *out, double lambda, int *error); void egads_betavariate(prngctx_t *ctx, double *out, double alpha, double beta, int *error); void egads_cunifvariate(prngctx_t *ctx, double *out, double mean, double arc, int *error);
The egads_randreal(
)
function produces a real number between 0 and
1 (inclusive) that is uniformly distributed across that space. To get
a real number in a particular range, use the function
egads_randuniform(
)
. For those needing random data in a
nonuniform distribution, there are numerous functions in the previous
API to produce random floats in various common distributions. The
semantics for these functions should be obvious to anyone who is
already familiar with the particular distribution.
void egads_randstring(prngctx_t *ctx, char *out, int len, int *error);
The function egads_randstring(
)
generates a random string that can contain
any printable character. That is, it produces characters between
ASCII 33 and ASCII 126 (inclusive) and thus contains no whitespace
characters. The output buffer must be allocated by the caller, and it
must be at least as long as the specified length plus an additional
byte to accommodate the terminating zero that the function will write
to the buffer.
void egads_randfname(prngctx_t *ctx, char *out, int len, int *error);
The function egads_randfname(
)
produces a random string suitable for use as
a filename. Generally, you are expected to concatenate the generated
string with a base path. This function expects the destination buffer
to be allocated already, and to be allocated with enough space to
hold the string plus a terminating NULL
, which
this function will add.
EGADS by Secure Software, Inc.: http://www.securesoftware.com/egads