We looked at the RNG seed sources recently when we noticed that the RNG when used as "new SecureRandom(new DigestRandomGenerator(new Sha256Digest()))" will always produce the same sequence. Entropy within a stream is fine but correlations ACROSS streams is a perfect 1.0 which is fatal performance for a RNG. Of course, it's due to non-singleton + default seed + digest mode but were surprised that the default behavior is to always use a seed of 0 rather than a pseudo-random seed. IMHO, the default seeding behavior of BC's SecureRandom is faulty and should be fixed. For testing/generating same sequences, one can always explicitly set the seed to 0, so that argument doesn't fly. Heck, even system clock ticks would be a one line fix and a big step from current seed of zero.
Anyway, going a step ahead, since system ticks isn't that great, take a look at https://gist.github.com/sidshetye/97631352f54a68184418 for mixing together additional sources of entropy like * Current process memory numbers * Other processes running on the system * OS environment variables mixed in The above is inspired from http://upokecenter.dreamhosters.com/articles/2011/04/entropy-source-random-s eed-generator-in-c/ which does NOT compile. That one spawns a background thread to capture entropy on a rolling basis and also mixes entropy from keyboard and mouse inputs - features not very suited for a library, so I didn't add them to the GitHub Gist. Ideally one should also be mixing in entropy from the processor's thermal diode IF the underlying processor allows it. Intel has RDRAND (https://software.intel.com/en-us/articles/intel-digital-random-number-gener ator-drng-software-implementation-guide) and for calling assembly from C# check http://stackoverflow.com/questions/959087/is-it-possible-to-execute-an-x86-a ssembly-sequence-from-within-c The RNG class interface could allow specifying what sources of entropy should be pulled in for those wanting to stay only in the managed code domain Example: SecureRandom( ., bool managedCodeOnly) { . } Cheers Sid From: Edward Ned Harvey (bouncycastle) [mailto:bouncycas...@nedharvey.com] Sent: Monday, July 28, 2014 11:55 PM To: dev-crypto-csharp@bouncycastle.org Subject: [dev-crypto-csharp] FYI - Low entropy in ThreadedSeedGenerator and DateTime.Now.Ticks Just FYI, I've been doing some statistical analysis on random numbers generated from various entropy sources. Here is a really simple test that has produced some illuminating results: Generate a bunch of random bytes. Then split it all out, one bit at a time (so if there's a pattern, it will be more easily recognizable). Compress it and see how compressible it is. (I'm using lzma from SharpCompress). So I create a list of RNG's. One of the RNG's is the zero RNG, which just produces an endless stream of zero's. This is in the list for the sake of calibration and as a test control. I create a byte array, say 64KB, and I populate it with random bytes from the first RNG. Split each bit out (now I have an array of 512KB), and compress it. Keep track of its compressed size. Repeat for each RNG in turn. After repeating with a dozen or so RNG's, I use the maximum one as the calibration point for assumed pure random, and I use the minimum one (the all-zero RNG) as the calibration point for completely worthless non-random. And then linearly scale each RNG result in between these two points, to estimate the number of entropy bits per bit of output. ThreadedSeedGenerator (with fast=false) is producing approx 0.7 bits of entropy per bit. ThreadedSeedGenerator (with fast=true) is producing approx 0.5 bits of entropy per bit. This is not a fatal flaw, as long as you're compensating for it - By default, SecureRandom seeds itself with one sample of Ticks, and 24 bytes (192 bits) of ThreadedSeedGenerator (with fast=true). By my estimation, this is approx 100-104 bits of entropy. And each subsequent call to SecureRandom adds another sample of Ticks seed material, which is approx 8 bits of entropy (at most). I really think each call to SecureRandom should get another 256 bits from ThreadedSeedGenerator (effectively adding another 128 bit seed), but that's me. Additionally, I measured the statistical randomness of each individual bit of Ticks, when sampled thousands of times with a Sleep(1) in between each sample. All the least significant 8 bits were indistinguishable from random. The 9th and 10th bit started deviating measurably, and after that, the deviation was very clear, but nonzero entropy until maybe the 29th bit or so. The total estimate of entropy in all the bits of a single sample of Ticks was about 14 bits, but realistically, only 8 bits looked random, so I wouldn't be comfortable trusting more than 2 or 4 bits of entropy from a single sample of Ticks.