19
$\begingroup$

It seemed to me that the Bouncy Castle SecureRandom class for C#/.NET only uses DateTime.Now.Ticks as its seed by default.

I was wrong, but wouldn't that be unsafe to do?

$\endgroup$
11
  • 4
    $\begingroup$ I see lots of questions about Bouncy Castle, here and on other SE sites. Is it really that bad? Should I start warning people whenever I see someone using it? $\endgroup$
    – otus
    Jul 18, 2014 at 19:42
  • 2
    $\begingroup$ Could you point me to the source, where they do that? Maybe add it to the question? Edit: Actually, I think I get it... $\endgroup$
    – otus
    Jul 18, 2014 at 20:04
  • 5
    $\begingroup$ I am sorry - I just stepped through code for the nineteenth time, and I just discovered I was wrong. YES, it's bad to use time as seed to prng, NO that's not all bouncy castle does. In fact, BC SecureRandom has a static instance called Master, which is seeded from Ticks and ThreadedSeedGenerator. The "SetSeed" method is confusing because it only adds seed material from Ticks; does not reduce the strength of the already present seed. $\endgroup$ Jul 18, 2014 at 20:25
  • 1
    $\begingroup$ That's only on J2ME where I don't think the system libraries have SecureRandom. Elsewhere it should use the system one, which should use OS entropy sources. $\endgroup$
    – otus
    Aug 5, 2014 at 7:20
  • 1
    $\begingroup$ AFAIU, when not on J2ME, it should use the SecureRandom class from the system libraries. It is technically implementation defined how that gets seeded, but usually something like this – i.e. reading /dev/[u]random for seed material. $\endgroup$
    – otus
    Aug 5, 2014 at 17:20

2 Answers 2

25
$\begingroup$

Yes, it is unsafe to seed a PRNG with only with the system time. No, that's not all Bouncy Castle's SecureRandom does.

The SecureRandom default constructor calls SetSeed(GetSeed(8)); which calls Master.GenerateSeed(length); which calls SetSeed(DateTime.Now.Ticks); which is misleading because SetSeed only adds seed material to an already existing prng (the static instance called Master). If you look at the static declaration for private static SecureRandom Master you'll see that it actually seeds itself from a combination of Ticks and ThreadedSeedGenerator.

Why the system time is not enough

Using just the system time would be unsafe. The whole point of a crypto random generator is to be unguessable by an adversary, and by using the system time as a seed to the random number generator, you make it easy for an adversary to guess your seed and hence your random output.

DateTime.Now.Ticks has precision of 10 million ticks per second. Suppose an attacker knows what time you generated a key, +/- 1 second. They only need to make 20 million guesses ($2^{20}$ or so) in order to guess your random seed. This is likely crackable in a matter of seconds with a modern laptop.

Suppose an attacker has absolutely no idea what time you generated some key. They only know it was after – let's say – the year 2000. Since it's 2014 now, the entire space of 14 years occupies 51-52 bits. log2(10000000*60*60*24*365*14) ~= 51.97… This means the absolute highest level of entropy that you're likely to have in anything generated from system time is around 51 bits, which is small enough to be easily crackable, and realistically, you'll never even come close to that.

$\endgroup$
4
$\begingroup$

All Bouncy Castle's random generator classes seem to derive from java.security.SecureRandom, where seed doesn't mean "initialize state to this". It means "stir in any entropy from this".

That means what they do is not insecure, but shouldn't actually help either, since java.security.SecureRandom is already seeded with entropy from the system (e.g. /dev/urandom).

I'm assuming the same is true for the C# version, though I don't use C# so I'm not sure.

$\endgroup$

Your Answer

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

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