[ Team LiB ] |
11.6 Reseeding a Pseudo-Random Number Generator11.6.1 ProblemYou have an application-level pseudo-random number generator such as the ones presented in Recipe 11.5, and you want to reseed it, either because you have new entropy to mix in or because you would like to prevent against backtracking attacks. 11.6.2 SolutionCreate a new seed by getting a sufficient number of bytes from the generator to seed the generator. If mixing in entropy, compress the entropy down to the seed size if necessary, as discussed in Recipe 11.16, then XOR the compressed seed with the generator output. Finally, reseed the generator with the resulting value. 11.6.3 DiscussionThere are two common reasons why you may want to reseed a PRNG. First, your threat model may include the possibility of the internal state of your PRNG being compromised, and you want to prevent against an attacker's being able to figure out numbers that were output before the state compromise. Reseeding, if done right, essentially transforms the internal state in a way that preserves entropy while making it essentially impossible to backtrack. Protecting against backtracking attacks can be done cheaply enough, so there is no excuse for not doing it. Second, you may want to add entropy into the state. This could serve a number of purposes. For example, you might want to add entropy to the system. Remember, however, that cryptographic generators have a maximum amount of entropy they can contain, so adding entropy to a generator state can look unnecessary. When available, however, reseeding with entropy is a good conservative measure, for several reasons. For one reason, if you have underestimated the amount of entropy that a generator has, adding entropy is a good thing. For another, if the generator has lost any entropy, new entropy can help replenish it. Such entropy loss is natural because cryptographic algorithms are not as good as their theoretical ideals. In addition, because we generally do not know the exact strength of our algorithms, it is hard to determine how quickly entropy gets lost. (Note, however, that if the algorithms are as strong as believed, it should be quite slowly.) While a generator based on AES or HMAC-SHA1, implemented as discussed in Recipe 11.5, probably never loses more than a miniscule amount of entropy before 264 outputs, it is always good to be conservative and assume that it drains quickly, particularly if you have entropy to spare.
The actions you should take to reseed a generator are different depending on whether you are actually adding entropy to the state of the generator or just trying to thwart a backtracking attack. However, the first step is the same in both cases.
For example, using the block cipher-based PRNG from Recipe 11.5, here is a function that reseeds the generator, given new, uncompressed data containing entropy: void spc_bcprng_reseed(SPC_BCPRNG_CTX *prng, unsigned char *new_data, size_t l) { size_t i; unsigned char m[SPC_MAX_KEYLEN + SPC_BLOCK_SZ]; SPC_BCPRNG_LOCK( ); if (prng->kl > SPC_MAX_KEYLEN) prng->kl = SPC_MAX_KEYLEN; spc_bcprng_rand(prng, m, prng->kl + SPC_BLOCK_SZ); while (l > prng->kl) { for (i = 0; i < prng->kl; i++) m[i] ^= *new_data++; l -= prng->kl; spc_bcprng_init(prng, m, prng->kl, m + prng->kl, SPC_BLOCK_SZ); spc_bcprng_rand(prng, m, prng->kl + SPC_BLOCK_SZ); } for (i = 0; i <l; i++) m[i] ^= *new_data++; spc_bcprng_init(prng, m, prng->kl, m + prng->kl, SPC_BLOCK_SZ); SPC_BCPRNG_UNLOCK( ); } To handle compression of the data that contains entropy, we avoid using a hash function. Instead, we break the data up into chunks no larger than the required seed size, and reseed multiple times until we have run out of data. This is an entropy-preserving way of processing the data that does not require the use of a cryptographic hash function. 11.6.4 See Also |
[ Team LiB ] |