Patent Publication Number: US-2006002550-A1

Title: Method and system for generation of cryptographic keys and the like

Description:
BACKGROUND OF THE INVENTION  
      The subject invention relates to a method and system for generating secret inputs, such as keys, to a cryptographic system. More particularly it relates to a method and system for generating inputs, typically in the form of binary strings, which are “hard” to guess. By “hard” herein is meant that given realistic computational resources a secret input cannot be discovered, given less than all the inputs used to create the secret input, in less than exponential time. Still more particularly it relates to a method and system for generating keys for digital postage meters which rely on cryptographic techniques to create secure, digitally printed postal indicia.  
      Encryption, Digital Signature algorithms, and Key Agreement Protocols and similar cryptographic systems rely on two basic assumptions to keep information secure:  
      1. The algorithms used are sound, and cannot be attacked directly. That means you cannot derive information about inputs to the algorithm that you did not know before hand; nor can you derive the output of the algorithm unless you know all the inputs.  
      2. Any secret input of the algorithm is hard to guess. Typically secret inputs are inputs such as: a secret key, a random value used for “blocking” (i.e. used to hide other information), or the private portion of a public key pair. (As used herein the terms “key” or “cryptographic key” are meant to include any string of random bits for cryptographic applications, such as a secret input or a hard to guess value from which a secret input is derived; e.g. a hard to guess value from which a public/private key pair is derived; as well as strings used in applications where the random bits become known and still strong security of the DRBG is required.)  
      Methods and systems such as that of the present invention (hereinafter sometimes “Deterministic Random Bit Generators” or “DRBG&#39;s”) are used to satisfy this second assumption, and are used throughout standard cryptographic protocols and operations such as: SSL/TLS Secure Sockets Layer Protocol, DSA—Digital Signature Algorithm, Diffie-Hellman Key Exchanges, RSA Encryption and Signing Algorithms, etc. DRBG&#39;s provide the basic hard to guess inputs to such cryptographic operations. Typically DRBG&#39;s include an initialization routine to generate an initial state variable, a generation routine to generate a requested secret input, and can include a reseed routine to recover security properties in the event the DRBG is compromised.  
      The current family of ANSI (American National Standards Institute) approved DRBG&#39;s (based on DES and SHA1 standards) are aging in the sense of being antiquated by newer algorithms and stronger security requirements. In fact DES is broken in the sense that a sub-exponential algorithm to break it is known.  
      Current security specifications for AES and ECC provide security that require on the order of 2 256  computational operations to break an algorithm. However, the present inventors are not aware of DRBG&#39;s that adequately provide that level of security; which reduces the security of algorithms using DRBG&#39;s because the second assumption discussed above is not fully satisfied at the strength of the algorithm. That is, while it may require 2 256  operations work to break the algorithm, it may only require 2 56  operations to discover the secret key used; which would then reduce overall security to 2 56  operations (in most cases).  
      It is also advantageous to provide a DRBG having a consistent, or “flat”, forward secrecy profile and backward secrecy, against all known state assumptions. Backward secrecy is the property that even with knowledge of the current state of the DRBG it remains hard to determine previous components of the state. A flat forward secrecy profile is the property that even with any (less than complete) knowledge of the current state it remains hard to predict future output of the DRBG, or future unknown components of the state.  
      Thus it is an object of the subject invention to provide a method and system for generating secret inputs which provides increased levels of security for cryptographic systems, and which has the properties of a flat forward secrecy profile and backwards secrecy.  
     BRIEF SUMMARY OF THE INVENTION  
      The above object is achieved and the disadvantages of the prior art are overcome in accordance with the subject invention by a method, and system operating in accordance with the method, for generating a random bit value that can be used, for example, as a cryptographic key which is hard to guess, by inputting a seed from an entropy source; generating an initial composite state as a function of the seed, the initial state comprising a plurality of components, the components including at least an initial state component and a state-update component; receiving a request to generate a random bit value; mixing all components of a current state, where the current state is initially the initial state, to generate an output string and a next state; then setting the current state to the next state, whereby the mixing of all components and setting the current state to a next state can be repeated to generate successive output strings with assurance of forward and backward secrecy; and deriving the requested random bit value from the at least one of the output strings.  
      As used herein “mixing” a set of values means generating an output as a function of all the values where the function has the property that it is hard (as “hard” is defined herein) to determine the output, or to recover the set of values from the output, with less than full knowledge of the set.  
      In accordance with one aspect of the subject invention the components are generated by mixing the seed with itself or with other information. The seed can be mixed using a codebook key definition function, a hash function, or a keyed hash function.  
      In accordance with another aspect of the subject invention the components are mixed using a codebook function, a hash function, or a keyed hash function.  
      A codebook key definition function “cb_kdf” is based on codebook encryption function cb, which is preferably a known function such as DES or AES. A codebook function is an encryption function of the form cb(&lt;input&gt;, &lt;key&gt;) that operates on a fixed length block of data &lt;input&gt; with a key,&lt;key&gt; by mixing it as well as introducing randomness (derived from &lt;key&gt;) into the output block. Suitable, known codebook functions are DES and AES. As used herein the term codebook key definition function means a function which has the form has the form cb_kdf(&lt;output length&gt;, &lt;key&gt;, &lt;input 1 &gt;, &lt;input 2 &gt;, . . . ) and compacts or expands a convenient function of &lt;input 1 &gt;, &lt;input 2 &gt;. . . , to generate an operand of appropriate length, then applies the encryption function cb to the operand, using &lt;key&gt; as the secret key, to generate an output of length &lt;output length&gt;.  
      In accordance with another aspect of the subject invention the output string is specified to be n bits in length and the components are mixed m times, each time generating a substring r bits in length, where m times r is greater than or equal to n and the output string is chosen to be n predetermined bits of a concatenation of the substrings.  
      In accordance with another aspect of the subject invention the initial state is generated using a codebook key definition function by: a) determining a seed s, the seed s having k bits of entropy; b) determining parameters CB_KEY_LENGTH and CB_WIDTH, each of the parameters being greater than or equal to k; c) determining application constants KEY_CONST 1 , KEY_CONST 2 , KEY_CONST 3 , C_CONST, and V_CONST; d) setting a codebook key, kdk, equal to CB_KEY_LENGTH predetermined bits of the seed s; e) computing a component K 1  as a codebook key derivation function: cb_kdf(CB_KEY_LENGTH, kdk, s, KEY_CONST 1 ); f) computing a component K 2  as a codebook key derivation function: cb_kdf(CB_KEY_LENGTH, kdk, s, KEY_CONST 2 ); g) computing a component K 3  as a codebook key derivation function: cb_kdf(CB_KEY_LENGTH, kdk, s, KEY_CONST 3 ); h) computing a component V 0  as a codebook key derivation function: cb_kdf(CB_KEY_LENGTH, kdk, s, V_CONST); i) computing a component C as a codebook key derivation function: cb_kdf(CB_KEY_LENGTH, kdk, s, C_CONST); j) setting an index component i equal to 1; and k) outputting an initial state S 0  comprising the components:V 0 , i, C, K 1 , K 2 , and K 3 .  
      In accordance with another aspect of the subject invention all components of a current state S j  (state S j  including components V 0 , i, C, K 1 , K 2 , and K 3 ) are mixed to generate an output string and a next state S j+1  by: a) determining the state S j ; b) determining a length n for the output string, and a rate r; c) setting an integer value m equal to the smallest integer greater than length n divided by rate r, where r is an integer greater than 0 and less than or equal to the length of component C; d) setting a variable V equal to the component V j ; e) setting an index q equal to 1; f) computing a variable M as a codebook function: M=cb(VxorC, K 1 ), where “xor” represents an exclusive or operation; g) determining auxiliary data dt (which is preferably date and time); h) computing a variable I as an auxiliary mixing function af having at least the operands dt, i, and M; i) computing a variable W as a codebook function: W=cb(VxorI, K 2 ); j) computing a variable V as a codebook function: V=cb(VxorM, K 3 ); k) setting a variable R q  equal to r predetermined bits of the variable W; l) setting the component i equal to i+1, and the index q equal to q+1; m) if the index q is not equal to m+1, returning to f; otherwise n) setting a next component V j+1  equal to the variable V; o) computing the output string as n predetermined bits of a concatenation of variables R q , where q equals 1 to m; whereby the next state S j+1  is determined as including (V j+1 , i, C, K 1 , K 2 , K 3 ).  
      In accordance with still another aspect of the subject invention the initial state is generated using a hash function by: a) determining a seed s, the seed s having 2*k bits of entropy; b) computing a component V 0  as hash function: hash(s); c) computing a component C as hash function: hash(s|V 0 ); d) setting an index component i equal to 1; and e) outputting an initial state S 0  comprising the components: V 0 , i, C.  
      In accordance with still another aspect of the subject invention all components of a current state Sj (state S j  including components V j , i, C) are mixed using a hash function by: a) determining the state S j ; b) determining a length n for the output string, and a rate r and a parameter HASH_DIGESTSIZE; c) setting an integer value m equal to the smallest integer greater than length n divided by rate r, where r is an integer greater than 0 and less than or equal to HASH_DIGESTSIZE+1; d) computing a variable V as a hash function having at least operands C and V j ; e) setting an integer value m equal to the smallest integer greater than length n divided by rate r, where r is an integer greater than 0 and less than or equal to the length of component C; f) setting an index q equal to 1; g) computing a variable x as a hash function: x=hash(V); h) setting a variable w q  equal to r predetermined bits of the variable x; i) computing the variable V as a function: V=V+1 (mod 2 HASH     —     DIGESTSIZE ); j) setting the index q equal to q+1; k) if the index q is not equal to m+1, returning to substep g; otherwise l) computing the output string as n predetermined bits of a concatenation of variables w q , where q equals 1 to m; and m) computing a next component V j+1  as a hash function: V j+1 =hash(V+y j +i(mod 2 HASH     —     DIGESTSIZE )); whereby the next state S j+1  is determined as including (V j+1 , i, C).  
      In accordance with still another aspect of the subject invention the initial state is generated using a keyed hash function by: a) determining seed s 1  and s 2 , the seeds s 1  and s 2  having 2*k bits of entropy; b) computing a component V 0  as hash function: hash(s 1 ); c) computing a component key K as hash function: hash(s 2 |V 0 ); d) computing a component C as keyed hash function: khash(V 0 , K); d) setting an index component i equal to 1; and e) outputting an initial state S 0  comprising the components: V 0 , i, C, K.  
      In accordance with still another aspect of the subject invention all components of a current state Sj (state S j  including components V j , i, C, K) are mixed using a keyed hash function to generate an output string and a next state S j+1  by: a) determining the state S j ; b) determining a length n for the output string, and a rate r and a parameter HASH_DIGESTSIZE; c) setting an integer value m equal to the smallest integer greater than length n divided by rate r, where r is an integer greater than 0 and less than or equal to HASH_DIGESTSIZE+1; d) computing a variable V as a keyed hash function having at least operands C and V j , and key K; e) setting an index q equal to 1; f) setting an integer value m equal to the smallest integer greater than length n divided by rate r, where r is an integer greater than 0 and less than or equal to the length of component C; g) computing a variable x as a keyed hash function: x=khash(V, K); h) setting a variable w q  equal to r predetermined bits of the variable x; i) compute the variable V as a function: V=V+1(mod 2 HASH     —     DIGESTSIZE ) j) setting the index q equal to q+1; k) if the index q is not equal to m+1, returning to substep g; otherwise l) computing the output string as n predetermined bits of a concatenation of variables w q , where q equals 1 to m; and m) computing a next component V j+1  as a hash function: V j+1 =hash(V+y j +i(mod 2 HASH     —     DIGESTSIZE )); whereby the next state S j+1  is determined as including (V j+1 , i, C, K).  
      Other objects and advantages of the subject invention will be apparent to those skilled in the art from consideration of the detailed description set forth below and the attached drawings. 
    
    
     BRIEF DESCRIPTION OF THE DRAWINGS  
       FIG. 1  shows a schematic block diagram of an encryption system comprising a DRBG in accordance with the subject invention.  
       FIG. 2  shows a generalized flow diagram of a method for generating a cryptographic key.  
       FIGS. 3   a,    3   b,  and  3   c  show a flow diagram of a codebook function based method for generating a cryptographic key.  
       FIGS. 4   a,    4   b ,  and  4   c  show a flow diagram of a hash function based method for generating a cryptographic key.  
       FIGS. 5   a,    5   b,  and  c  show a flow diagram of a keyed hash function based method for generating a cryptographic key. 
    
    
     DETAILED DESCRIPTION OF PREFERRED EMBODIMENTS OF THE INVENTION  
      In  FIG. 1  system  10  is a generalized encryption system. Encryption engines  12  receive clear text messages CT and combine them with a secret input (hereinafter sometimes a “key” or “cryptographic key” or “encryption key”) in accordance with an encryption standard such as the symmetric key standard, DES; or the public key standard, RSA to generate encryptions E. The encryptions are the then sent to decryption engine  14  in any convenient manner where they are decrypted using the appropriate decryption key (which can be the same as the encryption key or may be part of an encryption/decryption key pair) to recover messages CT for further distribution. (Only one engine  14  is shown for simplicity of illustration.) Without knowledge of the keys used it is hard to recover messages CT (or at least more costly than the value of the information obtained would justify). System  10  can also carry out other cryptographic operations such as digital signing of messages in a substantially similar manner. In a preferred embodiment of the subject invention encryption engines  12  are digital postage meters such as the FIPS meter marketed by the assignee of the present patent application which use cryptographic techniques to authenticate digitally printed postal indicia and decryption engine  14  is incorporated in postal service mail handling systems to validate the indicia on mail pieces printed by the meters.  
      History shows, however, that in time any secret can be learned. System  10  therefore includes key generation system  15  for generating new keys from time to time as necessary. (The new keys must of course be distributed to engines  12  and  14  in a secure manner through secure communications link  17 . This can be done in any convenient manner, details of which form no part of the subject invention.) System  15  includes DRBG  16 , (which is typically implemented as an application run on a programmed data processing system) data store  20  for storing algorithms and constants used to generate keys, input  24  for input of various parameters used to specify the keys to be generated, and entropy source  28  for generating seed values used to initialize or reseed DRBG  16 ; as will be described further below.  
      Entropy source  28  is a conventional apparatus which generates random output values based on measurement of physical phenomena. Typically entropy sources are based on apparatus such as ring oscillators, pluralities of high speed clocks and the drift among them, radioactive decay, and keystroke timing. While such entropy generators do produce numbers which are random in the sense that they are practically unpredictable, or in the case of radioactive decay truly unpredictable, they have proven to be unsatisfactory for directly generating keys for two reasons: the output is not flat, i.e. all output values are not equally likely; and known entropy sources are too slow to generate the large number of keys needed for large cryptographic systems.  
       FIG. 2  shows a flow diagram of the general operation of DRBG  16  in accordance with the subject invention. In  FIG. 2  values for parameters such as security parameters, user inputs, output bit string length, and purpose, (which will be described further below with respect to particular preferred embodiments of the subject invention) are considered to be predetermined.  
      At step  30  DRBG  16  calls for a seed s from entropy source  18 . Preferably seed s will have an entropy value proportional to k (typically k or 2* k), where k is a predetermined parameter representative of a desired level of security.  
      As understood in the art entropy is a mathematical measure of the amount of information provided by observation of the state of a variable. Here the variable seed s is a binary bit string. It is easily shown that if entropy source  18  is flat, i.e. all values of s are equally likely, that observation of the state of s, where s is 2* k bits in length, provides 2* k bits of entropy. However since, in general, entropy sources are not flat, s typically must be more than 2* k bits in length to provide 2* k bits of entropy.  
      At step  32  DRBG  16  computes initial composite state S 0  which includes at least components V 0  and C. Preferably components V 0  and C are computed by mixing seed s, either with itself or with other information; which can include a second seed s&#39; and predetermined constants.  
      At step  34  DRBG  16  sets j=0 and at step  36  waits for a request for a key to be generated. When a request is received, at step  40  DRBG  16  mixes all components of state S j , to generate a new state S j+1  and an output string y j  of predetermined length. At step  44  new key K(y j ) is output and, at step  48 , j is set to j+1 and DRBG returns to step  36 .  
      Those skilled in the art will recognize that K(y j ) can be simply y j  itself or can be a function of y j , sometimes complicated; as where K(y j ) is actually an encryption/decryption (or public/private) key pair. Such derivations of K(y j ) are well known and details of them form no part of the subject invention. For simplicity of description K(y j ) will be assumed equal to y j  in the detailed description below.  
       FIGS. 3   a,    3   b,  and  3   c  show detailed flow diagrams of the operation of DRBG  16  in accordance with a preferred embodiment of the subject invention which uses a conventional codebook encryption function, “cb” to mix components of state S j .  
      In  FIG. 3   a,  an initialization routine is shown, where at step  50 , DRBG  16  inputs security parameter k, which defines the level of security required, and mask pmask, which defines the purpose for which secret inputs y j  are to be generated.  
      Advantageously, particular instances of DRBG&#39;s can be limited to particular purposes, such as, for example, for generation of random values that will become known, i.e. a signing application, or for generation of random values that will be kept secret, i.e. symmetric key encryption. During initialization DRBG  16  inputs pmask which is a bit mask that specifies the particular instance of DRBG  16  is enabled only to generate keys y j  for specified purposes. For example, in pmask: 
          Bit  0 =private use     Bit  1 =public use     Bit  2 =Diffie-Hellman     Bit  3 =RSA Signing     Bit  4 =DSA Signing     . . . Other known cryptographic uses for secret inputs 
 
 As will be described further below, when a call is made to DRBG  16  to generate a secret input it returns an error message unless the purpose of that call is consistent with pmask. 
       

      At step  52  DRBG  16  calls seed s from entropy source  28 ; seed s having at least k bits of entropy. At step  54  it inputs constants CB_KEY_LENGTH and CB_WIDTH (both greater than or equal to k) from data store  20  as determined by parameter k.  
      At steps  56  and  60  DRBG  16  inputs optional constant t, if used. At step  62  application constants KEY_CONST 1 , KEY_CONST 2 , KEY_CONST 3 , C_CONST, and V_CONST are input. Preferably these constants are varied to associate particular instantiations of the DRBG with different users or applications.  
      At step  64  codebook key kdk is set equal to the first CB_KEY_LENGTH bits of s. At step  68  the component K 1  is computed as: 
 
cb_kdf(CB_KEY_LENGTH, kdk, s, KEY_CONST 1 ) 
 
 At steps  70 ,  72   76 , and  78  components K 2 , K 3 , C, and V 0  are computed similarly; substituting KEY_CONST 2 , KEY_CONST 3 , C_CONST, and V_CONST for KEY_CONST 1 , respectively. 
 
      At step  80  index i is set equal to 1, and at step  84  initial state S 0 =(V 0 , C, i, K 1 , K 2 , K 3 , t(if used)) of compound state variable S j  is returned and DRBG  16  exits.  
       FIG. 3   b  shows the operation of DRBG  16  in generating requested secret input y j . At step  90  current state S j  is called. At step  92  DRBG  16  inputs parameters n, r, and p; where n specifies the length of y j , r specifies the rate at which y j  will be generated, as will described further below, and p specifies the purpose for which y j  will used.  
      At steps  94 ,  96 , and  100  optional user input u j  is input. A default value of 0 is assumed if u j  is not supplied.  
      At step  102  p is tested for consistency with pmask to determine if the intended use is one which is permitted for DRBG  16 , and at step  104  r is tested to determine if it is greater than 0 and less than CB_WIDTH+1. If either test is failed an appropriate error message is returned at steps  108  or  110  respectively, and DRBG  16  exits.  
      If both tests are passed, at step  112  m, the number of cycles needed to compute y j  at a rate of r bits a cycle, is computed as: 
 
 m =ceiling( n/r )(the smallest integer greater than or equal to  n/r ); 
 
 the variable V is set equal to V j  and index q is set equal to 1. 
 
      Then at step  116  variable M is computed as: 
 
 M=cb ( VxorC, K   1 ); 
 
 where cb is the underlying codebook function described above with key K 1  and “xor” represents an exclusive or operation. 
 
      At step  118  DRBG  16  gets auxiliary information dt, which is preferably date and time information and also preferably will vary for each cycle; and at step  120  computes variable I as: 
 
 I=af (( dt, i, u   j    M ); 
 
 where function af is a predetermined mixing function which preferably has the form: 
 
 I=dt+u   j   +i+M (mod 2 drbg→width ); 
 
 where “drbg→width” is the width of the underlying block on which the underlying codebook function is defined: e.g. for cb=DES−64 bits, cb=AES−128 bits, etc. In other embodiments of the subject invention function af can be a conventional hashing function. 
 
      Then at step  124  variable W is computed as: 
 
 W=cb ( Vxorl, K   2 ); 
 
 and then at step  126  variable V is computed as: 
 
 V=cb ( VxorM, K   3 ). 
 
 Where steps  124  and  126  are carried in substantially the same manner as step  116  described above. 
 
      At step  128  variable R q  is set equal to the first r bits of variable W, and at step  132  indices i and q are set equal to i+1 and q+1 respectively. Then at step  134  index q is tested to determine if it is equal to m+1. If so, DRBG  16  returns to step  116  to compute another cycle of R q .  
      Otherwise, at step  136  V j+1  is set equal to V, and at step  140  secret input y j  is computed as: 
 
 y   j =the first  n  bits of  R   1   |R   2   | . . . |R   m ; where “|” represents concatenation. 
 
      At step  142  DRBG  16  returns next state S j+1  as: 
 
 S   j+1 =( V   j+1   , i, C, K   1 ,  K   2 ,  K   3 ,  t (if used)); 
 
 outputs secret input y j  and exits. 
 
      In  FIG. 3   c  a reseed routine is shown. It is known to use reseed routines to recover the property of forward secrecy for DRBG  16  when some or all of the constants KEY_CONST 1 , etc. become known. In the subject invention this is achieved in a novel manner by mixing the components of the current state S j  with a new seed s and new constants to generate a reseeded composite state S j+1 .  
      In  FIG. 3   c,  at step  150 , DRBG  16  inputs security parameter k, which defines the level of security required, and current state S j .  
      At step  152  DRBG  16  calls seed s from entropy source  28 ; seed s having at least k bits of entropy. At step  154  it inputs constants CB_KEY_LENGTH and CB_WIDTH (both greater than k) from data store  20  as determined by parameter k.  
      At steps  156  and  160  DRBG  16  inputs optional constant t, if used. At step  162  it determines if the input values for k and t are consistent with state S j . If not at step  164  it returns an appropriate error message and exits.  
      Otherwise, at step  168  application constants KDK_CONST, KEY_RESEED_CONST 1 , KEY_RESEED_CONST 2 , KEY_RESEED_CONST 3 , C_RESEED_CONST, and V_RESEED_CONST are input.  
      At step  170  codebook key kdk is computed as: 
 
 kdk=cb   —   kdf ( CB _KEY_LENGTH,  K   1 ,  s, V   j   , i, C, K   2 ,  K   3 ,  t, KDK _CONST); 
 
 where cb_kdf is the function described above with respect to the initialization routine. 
 
      At step  172  the component K 1  is computed as: 
 
cb_kdf(CB_KEY_LENGTH, kdk, s, KEY_RESEED_CONST 1 ) 
 
 At steps  176 ,  178 ,  180 , and  184  components K 2 , K 3 , C, and V j+1  are computed similarly; substituting KEY_RESEED_CONST 2 , KEY_RESEED_CONST 3 , V_RESEED_CONST, and C_RESEED_CONST for KEY_RESEED_CONST 1 , respectively. 
 
      At step  186  the new values for K 1 , etc. re tested to determine if they are consistent with state S j , and if not an appropriate error message is returned at step  188  and DRBG  16  exits.  
      Otherwise, at step  192  index i is set equal to 1, and at step  194  reseeded state S j+1 =(V j+1 , C, i, K 1 , K 2 , K 3 , t(if used)) of compound state S j  is returned and DRBG  16  exits.  
      In another embodiment of the subject invention the initialization routine of  FIG. 3   a  and reseed routine of  FIG. 3   c  can be modified to produce only a single key and the generation routine of  FIG. 3   b  can be modified to use that key in place of keys K 1 , K 2 , and K 3 .  
       FIGS. 4   a,    4   b,  and  4   c  show detailed flow diagrams of the operation of DRBG  16  in accordance with another preferred embodiment of the subject invention, which uses a conventional hashing function, “hash,” to mix components of state S j . (A hashing function operates on an input of arbitrary length to generate an output of predetermined size, the “digest length”, which is, with high probability, unique to the input. The recipient of a message and corresponding hash can thus be assured that the message was not altered after the hash was generated.) A suitable hash is SHA1.  
      In  FIG. 4   a,  an initialization routine is shown, where at step  200 , DRBG  16  inputs security parameter k, which defines the level of security required, and mask pmask, which defines the purpose for which secret inputs y j  are to be generated, as described above.  
      At step  202  DRBG  16  calls seed s from entropy source  28 ; seed s having at least 2* k bits of entropy. At step  206  it inputs constant HASH_DIGESTSIZE, defining the output size for the hash function (typically 2* k bits), from data store  20  as determined by parameter k.  
      At steps  210  and  212  DRBG  16  inputs optional constant t, if used.  
      At step  214  the component V 0  is computed as: 
 
 V   0 =hash( s ) 
 
      At step  218  the component C is computed as: 
 
 C= hash( s|V   0 ); where “|” again represents concatenation. 
 
      At step  220  index i is set equal to 1, and at step  222  initial state S 0 =(V 0 , C, t(if used)) of compound state variable S j  is returned and DRBG  16  exits.  
       FIG. 4   b  shows the operation of DRBG  16  in generating requested secret input y j  in accordance with the present hash based embodiment. At step  230  current state S j  is called. At step  232  DRBG  16  inputs parameters n, r, and p; where n specifies the length of y j , r specifies the rate at which y j  will be generated, as will described further below, and p specifies the purpose for which y j  will used.  
      At steps  234 ,  236 , and  240  optional user input u j  is input. A default value of 0 is assumed if u j  is not supplied.  
      At step  242  p is tested for consistency with pmask to determine if the intended use is one which is permitted for DRBG  16 , and at step  244  r is tested to determine if it is greater than 0 and less than HASH_DIGESTSIZE+1. If either test is failed an appropriate error message is returned at steps  248  or  250  respectively, and DRBG  16  exits.  
      If both tests are passed, at step  252  m, the number of cycles needed to compute y j  at a rate of r bits a cycle, is computed as: 
 
 m= ceiling( n/r ); 
 
 the variable V is computed as: 
 
 V= hash( u   j   |C|V   j ); and 
 
 index q is set equal to 1. 
 
      Then at step  256  variable x is computed as: 
 
 x= hash( V ); 
 
 and at step  258  variable w q  is set equal to the first r bits of x. 
 
      At step  260  variable V is computed as: 
 
 V=V+ 1(mod 2 HASH     —     DIGESTSIZE ). 
 
      At step  264  index q is set equal to q+1. Then at step  266  index q is tested to determine if it is equal to m+1. If so, DRBG  16  returns to step  116  to compute another cycle of w q .  
      Otherwise, at step  268  secret input y j  is computed as: 
 
 y   j =the first  n  bits of  w   1   |w   2   | . . . |w   m ; 
 
 and at step  272  V j+1  is computed as: 
 
 V   j+1 =hash( V+y   j+1   +i (mod 2 HASH     —     DIGESTSIZE )) 
 
      At step  274  indices i and j are set equal to i+1 and j+1 respectively; and at step  276  DRBG  16  returns next state S j+1  as: 
 
 S   j+1 =( V   j+1   , i, C, t (if used)); and 
 
 outputs secret input y j  and exits. 
 
      In  FIG. 4   c  a reseed routine is shown in accordance with the present embodiment. In  FIG. 4   c,  at step  280 , DRBG  16  inputs security parameter k, which defines the level of security required, and current state S j .  
      At step  282  DRBG  16  calls seed s from entropy source  28 ; seed s having at least 2* k bits of entropy.  
      At steps  284  and  286  DRBG  16  inputs optional constant t, if used. At step  290  it determines if the input values for k and t are consistent with state S j . If not at step  292  it returns an appropriate error message and exits.  
      At step  294  component V j+1  is computed as: 
 
 V   j+1 =hash( s|V   j   |i|C ). 
 
      At step  298  component C is computed as: 
 
 C= hash( s|V   j+1 ) 
 
      At step  300  index i is set equal to 1, and at step  302  reseeded state S j+1 =(V j+1 , i, C, t(if used)) of compound state variable S j  is returned and DRBG  16  exits.  
       FIGS. 5   a,    5   b,  and  5   c  show detailed flow diagrams of the operation of DRBG  16  in accordance with another preferred embodiment of the subject invention, which uses a conventional keyed hashing function, “khash,” to mix components of state S j . A keyed hashing function operates on an input of arbitrary length and a secret key to generate an output of predetermined size, the “digest length”, which is, with high probability, unique to the input and key. The recipient of a message and corresponding hash can thus be assured that the message was not altered after the hash was generated, and was produced by someone with the key. A suitable keyed hash is HMAC.  
       FIG. 5   a  shows the initialization of DRBG  16 . In  FIG. 5   a,  an initialization routine is shown, where at step  310 , DRBG  16  inputs security parameter k, which defines the level of security required, and mask pmask, which defines the purpose for which secret inputs y j  are to be generated, as described above.  
      At step  312  DRBG  16  calls seeds s 1  and s 2  from entropy source  28 ; each having at least 2* k bits of entropy. At step  314  it inputs constant HASH_DIGESTSIZE, defining the output size for the hash and khash functions (typically 2* k bits), from data store  20  as determined by parameter k.  
      At steps  316  and  320  DRBG  16  inputs optional constant t, if used.  
      At step  322  the component V 0  is computed as: 
 
 V   0 =hash( s   1 ); using a conventional hashing function such as SHA1 
 
      At step  324  the component K is computed as: 
 
 K =hash( s   2   |V   0 ). 
 
      At step  328  the component C is computed as: 
 
 C=k hash( V   0   , K ) 
 
      At step  340  index i is set equal to 1, and at step  342  initial state S 0 =(V 0 , i, C, K, t(if used)) of compound state variable S j  is returned and DRBG  16  exits.  
       FIG. 5   b  shows the operation of DRBG  16  in generating requested secret input y j  in accordance with the present keyed hash based embodiment. At step  350  current state S j  is called. At step  352  DRBG  16  inputs parameters n, r, and p; where n specifies the length of y j , r specifies the rate at which y j  will be generated, as will described further below, and p specifies the purpose for which y j  will used.  
      At steps  354 ,  356 , and  360  optional user input u j  is input. A default value of 0 is assumed if u j  is not supplied.  
      At step  362  p is tested for consistency with pmask to determine if the intended use is one which is permitted for DRBG  16 , and at step  364  r is tested to determine if it is greater than 0 and less than HASH_DIGESTSIZE+1. If either test is failed an appropriate error message is returned at steps  368  or  370  respectively, and DRBG  16  exits.  
      If both tests are passed, at step  372  m, the number of cycles needed to compute y j  at a rate of r bits a cycle, is computed as: 
 
 m =ceiling( n/r ); 
 
 the variable V is computed as: 
 
 V=k hash( u   j   |C|V   j   , K ); and 
 
 index q is set equal to 1. 
 
      Then at step  376  variable x is computed as: 
 
 x=k hash( V, K ); 
 
 and at step  378  variable w q  is set equal to the first r bits of x. 
 
      At step  380  variable V is computed as: 
 
 V=V+ 1(mod 2 HASH     —     DIGESTSIZE ). 
 
      At step  384  index q is set equal q+1. Then at step  386  index q is tested to determine if it is equal to m+1. If not, DRBG  16  returns to step  116  to compute another cycle of w q .  
      Otherwise, at step  388  secret input y j  is computed as: 
 
 y   j =the first  n  bits of  w   1    |w   2   | . . . |w   m ; 
 
 and at step  392  V j+1  is computed as: 
 
 V   j+1 =hash( V+y   j   +i (mod 2 HASH     —     DIGESTSIZE )) 
 
      At step  394  indices i and j are set equal to i+1 and j+1 respectively; and at step  396  DRBG  16  returns next state S j+1  as: 
 
 S   j+1 =( V   j+1   , i, C, K, t (if used)); and 
 
 outputs secret input y j  and exits. 
 
      In  FIG. 5   c  a reseed routine is shown in accordance with the present embodiment. In  FIG. 5   c,  at step  400 , DRBG  16  inputs security parameter k, which defines the level of security required, and current state S j .  
      At step  402  DRBG  16  calls seeds s, and S 2  from entropy source  28 ; each having at least 2* k bits of entropy.  
      At steps  404  and  406  DRBG  16  inputs optional constant t, if used. At step  410  it determines if the input values for k and t are consistent with state S j . If not at step  412  it returns an appropriate error message and exits.  
      At step  414  component V j+1  is computed as: 
 
 V   j+1 =hash( s   1   |V   j   |i|C|K ). 
 
      At step  416  component K is computed as: 
 
 K =hash( s   2   |V   j+1 ). 
 
      At step  418  component C is computed as: 
 
 C=k hash( V   j+1   , K ) 
 
      At step  420  index i is set equal to 1, And at step  422  reseeded state S j+1 =(V j+1 , i, C, K t(if used)) of compound state S j  is returned and DRBG  16  exits.  
      In other embodiments of the subject invention the operation of DRBG  16  in accordance with  FIGS. 5   a - 5   c  can be expanded to allow for multiple keys by passing additional seeds into the initialization routine of  FIG. 5   a  and the reseed routine of  FIG. 5   c.    
      The following Tables 1, 2 and 3 give pseudo-C source code listings for particular implementations of the preferred embodiments of  FIGS. 3   a - 3   c;    4   a - 4   c;  and  5   a - 5   c  respectively. Note that some functions are not fully defined in these listings. However those skilled in the art will be able to implement the code given in any convenient manner without further specification.  
                       TABLE 1                          #define   SUCCESS   0       #define   ERROR   0xFFFFFFFF       #define   MIN_ENTROPY_RATE   8       #define   MAX_ENTROPY   512       #define   MAX_SEED_LENGTH   MAX_ENTROPY*               MIN_ENTROPY_RATE                 typedef struct _cb_drbg{                         int k;           int klength;           int width;           byte *V;           byte *i           byte *C;           byte *K;           byte *t;                 }cb_drbg;       int aes_ecb(byte *out, byte *in, byte *key, int keylength, int cbwidth);       int aes_kdf(byte *out, int outlen, byte *key, int keylength, byte *input,       int inlength);       int entropy(byte *out, int *outlen, int k);       int validate_purpose(byte *t1, byte *t2);       int validate_new_drbg(cb_drbg *new, cb_drbg *old);       int initialize(cb_drbg *drbg, int k, byte *t)       {                         byte seed[MAX_SEED_LENGTH];           int slength = MAX_SEED_LENGTH;           if((k!=128)&amp;&amp;(k!=192)&amp;&amp;(k!=256)) { return ERROR; }           drbg-&gt;width = drbg-&gt;klength = k;           if(entropy(seed, &amp;slength, 2*k)) { return ERROR; }           if(validate_purpose(t, NULL)) {return ERROR; }           drbg-&gt;t = t;           drbg-&gt;i = 1;           if(aes_kdf(drbg-&gt;K,drbg-&gt;klength,seed,k,seed|“KEY”, slength+3))           { return ERROR; }           if(aes_kdf(drbg-&gt;V,drbg-&gt;width,seed,k,seed|“STATE”,slength+5))           { return ERROR; }           if(aes_kdf(drbg-&gt;C,drbg-&gt;width,seed,k,seed|“UPDATE”,           slength+6))           { return ERROR; }           return SUCCESS;                 }       int reseed(cb_drbg *drbg, int k, byte *t)       {                         byte seed[MAX_SEED_LENGTH], key[MAX_ENTROPY];           int slength = MAX_SEED_LENGTH;           cb_drbg olddrbg;           olddrbg = drbg;           if(k!=drbg-&gt;k) { return ERROR;           }           if(validate_purpose(drbg-&gt;t, t)) { return ERROR;           }           if(entropy(seed, &amp;slength, 2*k)) { return ERROR;           }           if(aes_kdf(key,k,seed,k,s|drbg-&gt;V|drbg-&gt;C|drbg-&gt;K,slength+drbg-&gt;                 width*2+drbg-&gt;klength))                         { return ERROR;           }                         if(aes_kdf(drbg-&gt;K,drbg-&gt;klength,key,k,seed|“KEY”,slength+3)           { return ERROR;           }           if(aes_kdf(drbg-&gt;V,drbg-&gt;width,key,k,seed|“STATE”,slength+5))           { return ERROR;           }           if(aes_kdf(drbg-&gt;C,drbg-&gt;width,key,k,seed|“UPDATE”,slength+6))           { return ERROR;           }           drbg-&gt;i = 1; drbg-&gt;t = t;           if(validate_new_drbg(drbg, olddrbg)) { return ERROR;           }           destroy(oldrbg);           return SUCCESS;                 }       int generate(byte *output, int length, cb_drbg *drbg, byte *user, int       ulength, int r,       byte *p)       {                         int l, m;           byte M[MAX_ENTROPY], I[MAX_ENTROPY],           S[MAX_ENTROPY];           if(validate_purpose(drbg-&gt;t, p)) { return ERROR;           }           if((r&lt;1)||(r&gt;drbg-&gt;width)) { return ERROR;           }           m = ceil(length/r);           for(l=0:l&lt;m;l++) {                         if(aes_ecb(M, drbg-&gt;V⊕ drbg-&gt;C, drbg-&gt;K, drbg-&gt;klength,                         drbg-&gt;width)){ return ERROR; }                         dt = get_datetime( );           I = dt + u j  + i + M(mod 2 drbg-&gt;,width ).           if(aes_ecb(S, drbg-&gt;V⊕I, drbg-&gt;K, drbg-&gt;klength,                         drbg-&gt;width)) { return ERROR; }                         if(aes_ecb(drbg-&gt;V,drbg-&gt;V⊕M,drbg-&gt;K,drbg-&gt;klkength,                         drbg-&gt;width)) { return ERROR; }                         output +|= leftmost r-bits of S; // +| meant to symbolize                 concatenate current fill                         drbg-&gt;i = drbg-&gt;i + 1;                         }           return SUCCESS;                 }                  
 
     
       
         
           
               
               
               
             
               
                 TABLE 2 
               
               
                   
               
               
                   
               
             
            
               
                 #define 
                 SUCCESS 
                 0 
               
               
                 #define 
                 ERROR 
                 0xFFFFFFFF 
               
               
                 #define 
                 MIN_ENTROPY_RATE 
                 8 
               
               
                 #define 
                 MAX_ENTROPY 
                 512 
               
               
                 #define 
                 MAX_SEED_LENGTH 
                 MAX_ENTROPY* 
               
               
                   
                   
                 MAX_ENTROPY_RATE 
               
               
                 #define 
                 SHA160_SECURITY 
                 80 
               
               
                 #define 
                 SHA224_SECURITY 
                 112 
               
               
                 #define 
                 SHA256_SECURITY 
                 128 
               
               
                 #define 
                 SHA384_SECURITY 
                 192 
               
               
                 #define 
                 SHA512_SECURITY 
                 256 
               
               
                 #define 
                 SHA160_DIGESTSIZE 
                 SHA160_SECURITY*2 
               
               
                 #define 
                 SHA224_DIGESTSIZE 
                 SHA224_SECURITY*2 
               
               
                 #define 
                 SHA256_DIGESTSIZE 
                 SHA256_SECURITY*2 
               
               
                 #define 
                 SHA384_DIGESTSIZE 
                 SHA384_SECURITY*2 
               
               
                 #define 
                 SHA512_DIGESTSIZE 
                 SHA512_SECURITY*2 
               
            
           
           
               
            
               
                 typedef struct _cb_drbg{ 
               
            
           
           
               
               
            
               
                   
                 int k; 
               
               
                   
                 int width; 
               
               
                   
                 byte *V; 
               
               
                   
                 byte *i 
               
               
                   
                 byte *C; 
               
               
                   
                 byte *t; 
               
            
           
           
               
            
               
                 }cb_drbg; 
               
               
                 int hash(byte *out, byte *in, int HASH); 
               
               
                 int entropy(byte *out, int *outlen, int k); 
               
               
                 int validate_purpose(byte *t1, byte *t2); 
               
               
                 int validate_new_drbg(cb_drbg *new, cb_drbg *old); 
               
               
                 int initialize(cb_drbg *drbg, int k, byte *t){ 
               
            
           
           
               
               
            
               
                   
                 byte seed[MAX_SEED_LENGTH]; 
               
               
                   
                 int slength = MAX_SEED_LENGTH; 
               
               
                   
                 if((k!=SHAXXX_SECURITY)) { return ERROR; } 
               
               
                   
                 drbg-&gt;width = SHAXXX_DIGESTSIZE; 
               
               
                   
                 drbg-&gt;k = k; 
               
               
                   
                 if(entropy(seed, &amp;slength, drbg-&gt;width)) { return ERROR; } 
               
               
                   
                 if(validate_purpose(t, NULL)) { return ERROR; } 
               
               
                   
                 drbg-&gt;t = t; 
               
               
                   
                 drbg-&gt;i = 1; 
               
               
                   
                 if(hash(drbg-&gt;V, seed, drbg-&gt;k)) { return ERROR; } 
               
               
                   
                 if(hash(drbg-&gt;C, seed | drbg-&gt;V, drbg-&gt;k)) { return ERROR; } 
               
               
                   
                 return SUCCESS; 
               
            
           
           
               
            
               
                 } 
               
               
                 int reseed(cb_drbg *drbg, int k, byte *t){ 
               
            
           
           
               
               
            
               
                   
                 byte seed[MAX_SEED_LENGTH]; 
               
               
                   
                 int slength = MAX_SEED_LENGTH; 
               
               
                   
                 cb_drbg olddrbg; 
               
               
                   
                 olddrbg = drbg; 
               
               
                   
                 if(k!=drbg-&gt;k) { return ERROR; 
               
               
                   
                 } 
               
               
                   
                 if(validate_purpose(drbg-&gt;t, t)) { return ERROR; 
               
               
                   
                 } 
               
               
                   
                 if(entropy(seed, &amp;slength, drbg-&gt;width)) { return ERROR; 
               
               
                   
                 } 
               
               
                   
                 if(hash(drbg-&gt;V, seed|drbg-&gt;V|drbg-&gt;i|drbg-&gt;C, drbg-&gt;k)) 
               
               
                   
                 { return ERROR; 
               
               
                   
                 } 
               
               
                   
                 if(hash(drbg-&gt;C, seed | drbg-&gt;V, drbg-&gt;k)) { return ERROR; } 
               
               
                   
                 drbg-&gt;i = 1; 
               
               
                   
                 if(validate_new_drbg(drbg, olddrbg)) { return ERROR; 
               
               
                   
                 } 
               
               
                   
                 destroy(olddrbg); 
               
               
                   
                 return SUCCESS; 
               
            
           
           
               
            
               
                 } 
               
               
                 int generate(byte *output, int length, cb_drbg *drbg, byte *user, int 
               
               
                 ulength, int r, 
               
               
                 byte *p){ 
               
            
           
           
               
               
            
               
                   
                 int l, m; 
               
               
                   
                 byte V[SHA512_DIGESTSIZE/8], X[SHA512_DIGESTSIZE/8]; 
               
               
                   
                 if(validate_purpose(drbg-&gt;t, p)) { return ERROR; 
               
               
                   
                 } 
               
               
                   
                 if((r&lt;1)||(r&gt;drbg-&gt;width)) { return ERROR; 
               
               
                   
                 } 
               
               
                   
                 m = ceil(length/r); 
               
               
                   
                 if(hash(V, user|drbg-&gt;C|drbg-&gt;V, drbg-&gt;k)) { return ERROR; 
               
               
                   
                 } 
               
               
                   
                 for(l=0:l&lt;m;l++){ 
               
            
           
           
               
               
            
               
                   
                 if(hash(X, V, drbg-&gt;k)) { return ERROR; 
               
            
           
           
               
               
            
               
                   
                 } 
               
            
           
           
               
               
            
               
                   
                 output +| = leftmost r-bits of X; // +| meant to symbolize 
               
            
           
           
               
            
               
                 concatenate current fill 
               
            
           
           
               
               
            
               
                   
                 V = V + 1 (mod 2 drbg-&gt;width ) 
               
            
           
           
               
               
            
               
                   
                 } 
               
               
                   
                 output = leftmost length-bits of output; 
               
               
                   
                 drbg-&gt;V = hash(V + output + drbg-&gt;i mod 2 drbg-&gt;width ,); 
               
               
                   
                 drbg-&gt;i = drbg-&gt;i + 1; 
               
               
                   
                 return SUCCESS; 
               
            
           
           
               
            
               
                 } 
               
               
                   
               
            
           
         
       
     
     
       
         
           
               
               
               
             
               
                 TABLE 3 
               
               
                   
               
               
                   
               
             
            
               
                 #define 
                 SUCCESS 
                 0 
               
               
                 #define 
                 ERROR 
                 0xFFFFFFFF 
               
               
                 #define 
                 MIN_ENTROPY_RATE 
                 8 
               
               
                 #define 
                 MAX_ENTROPY 
                 512 
               
               
                 #define 
                 MAX_SEED_LENGTH 
                 MAX_ENTROPY* 
               
               
                   
                   
                 MAX_ENTROPY_RATE 
               
               
                 #define 
                 SHA160_SECURITY 
                 80 
               
               
                 #define 
                 SHA224_SECURITY 
                 112 
               
               
                 #define 
                 SHA256_SECURITY 
                 128 
               
               
                 #define 
                 SHA384_SECURITY 
                 192 
               
               
                 #define 
                 SHA512_SECURITY 
                 256 
               
               
                 #define 
                 SHA160_DIGESTSIZE 
                 SHA160_SECURITY*2 
               
               
                 #define 
                 SHA224_DIGESTSIZE 
                 SHA224_SECURITY*2 
               
               
                 #define 
                 SHA256_DIGESTSIZE 
                 SHA256_SECURITY*2 
               
               
                 #define 
                 SHA384_DIGESTSIZE 
                 SHA384_SECURITY*2 
               
               
                 #define 
                 SHA512_DIGESTSIZE 
                 SHA512_SECURITY*2 
               
            
           
           
               
            
               
                 typedef struct _cb_drbg{ 
               
            
           
           
               
               
            
               
                   
                 int k; 
               
               
                   
                 int width; 
               
               
                   
                 byte *V; 
               
               
                   
                 byte *i 
               
               
                   
                 byte *C; 
               
               
                   
                 byte *K; 
               
               
                   
                 byte *t; 
               
            
           
           
               
            
               
                 }cb_drbg; 
               
               
                 int hash(byte *out, byte *in, int HASH); 
               
               
                 int khash(byte *out, byte *in, byte *key, int HASH); 
               
               
                 int entropy(byte *out, int *outlen, int k); 
               
               
                 int validate_purpose(byte *t1, byte *t2); 
               
               
                 int validate_new_drbg(cb_drbg *new, cb_drbg *old); 
               
               
                 int initialize(cb_drbg *drbg, int k, byte *t) 
               
               
                 { 
               
            
           
           
               
               
            
               
                   
                 byte seed[MAX_SEED_LENGTH]; 
               
               
                   
                 int slength = MAX_SEED_LENGTH; 
               
               
                   
                 if((k!=SHAXXX_SECURITY)) { return ERROR; } 
               
               
                   
                 drbg-&gt;width = SHAXXX_DIGESTSIZE; 
               
               
                   
                 drbg-&gt;k = k; 
               
               
                   
                 if(entropy(seed, &amp;slength, drbg-&gt;width)) { return ERROR; } 
               
               
                   
                 if(validate_purpose(t, NULL)) { return ERROR; } 
               
               
                   
                 drbg-&gt;t = t; 
               
               
                   
                 drbg-&gt;i = 1; 
               
               
                   
                 if(hash(drbg-&gt;V, seed, drbg-&gt;k)) { return ERROR; } 
               
               
                   
                 if(entropy(seed, &amp;slength, drbg-&gt;width)) { return ERROR; } 
               
               
                   
                 if(hash(drbg-&gt;K, seed | drbg-&gt;V, drbg-&gt;k)) { return ERROR; } 
               
               
                   
                 if(khash(drbg-&gt;C, drbg-&gt;V, drbg-&gt;K, drbg-&gt;k)) { return ERROR; } 
               
               
                   
                 return SUCCESS; 
               
            
           
           
               
            
               
                 } 
               
               
                 int reseed(cb_drbg *drbg, int k, byte *t) 
               
               
                 { 
               
            
           
           
               
               
            
               
                   
                 byte seed[MAX_SEED_LENGTH]; 
               
               
                   
                 int slength = MAX_SEED_LENGTH; 
               
               
                   
                 cb_drbg olddrbg; 
               
               
                   
                 olddrbg = drbg; 
               
               
                   
                 if(k!=drbg-&gt;k) { return ERROR; 
               
               
                   
                 } 
               
               
                   
                 if(validate_purpose(drbg-&gt;t, t)) { return ERROR; 
               
               
                   
                 } 
               
               
                   
                 if(entropy(seed, &amp;slength, drbg-&gt;width)) { return ERROR; 
               
               
                   
                 } 
               
               
                   
                 if(hash(drbg-&gt;V, seed|drbg-&gt;V|drbg-&gt;i|drbg-&gt;C|drbg-&gt;K, drbg-&gt;k)) 
               
               
                   
                 { return ERROR; 
               
               
                   
                 } 
               
               
                   
                 if(entropy(seed, &amp;slength, drbg-&gt;width)) { return ERROR; 
               
               
                   
                 } 
               
               
                   
                 if(hash(drbg-&gt;K, seed | drbg-&gt;V, drbg-&gt;k)) { return ERROR; 
               
               
                   
                 } 
               
               
                   
                 if(khash(drbg-&gt;C, drbg-&gt;V, drbg-&gt;K, drbg-&gt;k)) { return ERROR; 
               
               
                   
                 } 
               
               
                   
                 drbg-&gt;i = 1; 
               
               
                   
                 if(validate_new_drbg(drbg, olddrbg)) { return ERROR; 
               
               
                   
                 } 
               
               
                   
                 destroy(olddrbg); 
               
               
                   
                 return SUCCESS; 
               
            
           
           
               
            
               
                 } 
               
               
                 int generate(byte *output, int length, cb_drbg *drbg, byte *user, int 
               
               
                 ulength, int r, 
               
               
                 byte *p) 
               
               
                 { 
               
            
           
           
               
               
            
               
                   
                 int l, m; 
               
               
                   
                 byte V[SHA512_DIGESTSIZE/8], X[SHA512_DIGESTSIZE/8]; 
               
               
                   
                 if(validate_purpose(drbg-&gt;t, p)) { return ERROR; 
               
               
                   
                 } 
               
               
                   
                 if((r&lt;1)||(r&gt;drbg-&gt;width)) { return ERROR; 
               
               
                   
                 } 
               
               
                   
                 m = ceil(length/r); 
               
               
                   
                 if(khash(V, user|drbg-&gt;C|drbg-&gt;V, drbg-&gt;K, drbg-&gt;k)) { return 
               
            
           
           
               
            
               
                 ERROR; } 
               
            
           
           
               
               
            
               
                   
                 for(l=0:l&lt;m;l++){ 
               
            
           
           
               
               
            
               
                   
                 if(khash(X, V, drbg-&gt;K, drbg-&gt;k)) { return 
               
            
           
           
               
            
               
                 ERROR; } 
               
            
           
           
               
               
            
               
                   
                 output +| = leftmost r-bits of X; // +| meant to symbolize 
               
            
           
           
               
            
               
                 concatenate current fill 
               
            
           
           
               
               
            
               
                   
                 V = V + 1 (mod 2 drbg-&gt;width ) 
               
            
           
           
               
               
            
               
                   
                 } 
               
               
                   
                 output = leftmost length-bits of output; 
               
               
                   
                 drbg-&gt;V = V + output + drbg-&gt;i mod 2 drbg-&gt;width ; 
               
               
                   
                 drbg-&gt;i = drbg-&gt;i + 1; 
               
               
                   
                 return SUCCESS; 
               
            
           
           
               
            
               
                 } 
               
               
                   
               
            
           
         
       
     
      The embodiments described above and illustrated in the attached drawings have been given by way of example and illustration only. From the teachings of the present application those skilled in the art will readily recognize numerous other embodiments in accordance with the subject invention. Accordingly, limitations on the subject invention are to be found only in the claims set forth below.