[ Team LiB ] |
11.8 Getting Entropy or Pseudo-Randomness Using EGADS11.8.1 ProblemYou 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. 11.8.2 SolutionUse the EGADS API as described in the following Section 11.8.3. 11.8.3 DiscussionEGADS, 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:
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:
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:
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. 11.8.4 See Also
|
[ Team LiB ] |