3
$\begingroup$

There are limits to how much you can use a the DRBG before you have to reseed it, but are there any limits to how much you must use it before reseeding?

Take the following scenarios as an example…

Usually you seed the DRBG once, then you use that instance until you reach the reseed limit. Like so:

seed     = seedFromUrandom    // Reads entropy from /dev/urandom
genStart = drbgFromSeed seed
(v1, gen1) = genBytes genStart // Generates random data and the next state 
                               // of the DRBG as a tuple
/*
    Code using the random data in v1
*/
(v2, gen2) = genBytes gen1 // Generates more random data and the next state
                           // of the DRBG as a tuple. Note that gen1 is 
                           // used here and not genStart.
/*
    Code using the random data in v2
*/

What if you created a newly seeded instance each time you want to generate random data? Like so:

seed     = seedFromUrandom    // Reads entropy from /dev/urandom
genStart = drbgFromSeed seed
(v1, _)  = genBytes genStart // Generates random data and ignores the
                             // next instance of the DRBG.
/*
    Code using the random data in v1
*/
seed     = seedFromUrandom    // Reads entropy from /dev/urandom
genStart = drbgFromSeed seed
(v2, _)  = genBytes genStart // Generates random data and ignores the
                             // next instance of the DRBG.
/*
    Code using the random data in v2
*/

Please note:

  • When I say “DRBG”, I mean the NIST standardized number-theoretically secure random number generator. Either HMAC (SHA512), Hash (SHA512), or counter (AES 128).
  • Like stated in the pseudo-code, entropy is read from /dev/urandom.
$\endgroup$
3
  • $\begingroup$ Actually, the premise that you need to reseed periodically ain't necessarily so. Some documents might suggest that reseeding is mandatory, but if you choose a good DBRG, it's not strictly necessary. The decision of whether to reseed should be based upon a thoughtful risk analysis, not just a blind rule-based "the standard says I have to reseed so I guess I have to". $\endgroup$
    – D.W.
    Commented Feb 21, 2014 at 1:17
  • $\begingroup$ @D.W. I see! If the library documentation says that the DRBG must be reseeded, shouldn't I trust that? $\endgroup$ Commented Feb 24, 2014 at 11:17
  • $\begingroup$ rzetterberg, for most applications (if you can reseed), the advice in your library documentation is undoubtedly good advice. But for many DRBG's, that advice is probably more cautious than is really necessary. Therefore, if there's some reason why you can't re-seed, don't take that advice as gospel: do a risk analysis to see if it's really necessary. $\endgroup$
    – D.W.
    Commented Feb 24, 2014 at 17:10

2 Answers 2

6
$\begingroup$

/dev/urandom itself is an acceptable crypto-quality (P)RNG. Therefore it can't hurt security to call it as often as you want. Assuming that /dev/urandom operates correctly (i.e. returns bit that cannot be predicted), the probability for an observer to correctly predict the bits generated by drbgFromSeed decreases (very slowly) with the number of generated bits.

You could, in fact, read from /dev/urandom and never use a DRBG internally. There are reasons not to do that, but they aren't security:

  • The most common reason to avoid reading /dev/urandom too often is performance.
  • You may prefer to use a know PRNG internally and keep outside sources as strictly entropy injection. This would make your application portable to platforms that don't provide a usable PRNG, and you have to make do with something else (e.g. downloaded or pre-seeded entropy).
  • Using your own DRBG implementation (or a known good one) can help if you need to demonstrate the security of your application.
  • Maybe you need the determinism property at some point — but then you're better off using an explicit KDF.

What you need to be extremely careful of is never using the same DRBG state more than once. Discarding a DRBG state is fine. The DRBG state has an affine type (your syntax looks like Haskell, beware that without a monad to enforce linearity, the mistake of reusing a DRBG state is a lot more likely than in an imperative language).

$\endgroup$
5
  • $\begingroup$ The Fortuna CSPRNG is reseeded at most 10 times per second, so that an attacker who has compromised its state can't supply so much input to it that none of its pools gain enough entropy before being used that the attacker can't track them. $\endgroup$ Commented Feb 20, 2014 at 22:57
  • $\begingroup$ @BrockHansen I'm afraid I don't see how this relates to my answer. $\endgroup$ Commented Feb 20, 2014 at 22:59
  • $\begingroup$ @Gilles It's funny that you mention that my pseudo-code looks like Haskell, since I use Haskell predominantly. Anyway, not only did you answer my question, you also provided more information that answered other questions I had. So thank you very much for that! $\endgroup$ Commented Feb 24, 2014 at 11:26
  • $\begingroup$ Perhaps I'm not clear on the purpose of a DRBG, but it seems to me that the purpose of a deterministic random byte generator is lost if it isn't deterministic. Doesn't "solving" the reseeding problem of a DRBG using /dev/urandom mean that it isn't a DRBG any longer, ie. it is no longer deterministic? And indeed, if it isn't deterministic, why not drop it and use /dev/urandom exclusively? $\endgroup$
    – runeks
    Commented Mar 22, 2016 at 8:28
  • $\begingroup$ @runeks The most common use of a DRBG is to generate unpredictable data (i.e. data that isn't correlated with anything else). You can do that with a DRBG with an unpredictable seed. In my answer I give a few reasons to use a DRBG seeded with /dev/urandom to generate unpredictable data: performance, portability, demonstrable security. It's rare to actually need the determinism aspect; an example use case is when you want to keep logs of everything and you want to be able to repeat a run of the program, e.g. to debug it. $\endgroup$ Commented Mar 22, 2016 at 12:00
5
$\begingroup$

Too long for a comment...

The Haskell DRBG package makes you reseed every so often (2^48 requests, iirc) because that is what SP800-90 specified. Instead of reseeding, you could construct an auto-reseeding generator, which would have higher period, and genBytes from the exception module (so you don't have to deal with an Either type). Notice the second generator, the one performing the auto-reseed, could be one that never needs reseeding - such as SystemRandom.

$\endgroup$
1
  • $\begingroup$ Wow, an answer from the author of the actual library :) Thanks for the clarification! $\endgroup$ Commented May 19, 2014 at 10:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.