> From: Mat Robichaud [mailto:[email protected]]
> 
> connection--we are anticipating 10,000+. Should I share one SecureRandom
> object for all handlers for use in the TlsServerProcotol class, or should I 
> create
> a new SecureRandom for each handler?

Looking at the code now, I see:

crypto\src\security\SecureRandom.cs
lines 35 to 42

The SecureRandom PORTABLE static ctor seeds itself with the clock ticks (at 
most 8 or 14 bits entropy, realistically probably 4 bits), and 32 bytes from 
ThreadedSeedGenerator. There is a comment there, referencing the bug reported 
Aug 2014 http://www.bouncycastle.org/csharpdevmailarchive/msg00814.html about 
ThreadedSeedGenerator returning low entropy. The assumption seems to be that 
seeding with 16 bytes is probably sufficient, and if ThreadedSeedGenerator 
generates 32 bytes, it hopefully has 16 bytes entropy.

My personal feeling is that you should aim for seeding with 32 bytes, and 
assume 10% or 5% quality of entropy returned by ThreadedSeedGenerator. So I 
would seed with 320 to 640 bytes from ThreadedSeedGenerator. Also, the 
measurements that show ThreadedSeedGenerator to provide poor entropy were based 
on my Macbook Pro, and Windows VM. I don't know how/where to build/run/test the 
PORTABLE library. Ideally you'd want to measure the randomness of 
ThreadedSeedGenerator on the target platform where you intend to run it, 
because the nature of TSG is highly platform dependent. When you run TSG for 32 
bytes on your system, for all we know, you might be getting anywhere between 0 
and 256 bits of entropy.

To answer your question about instantiating just one, or more than one: If you 
use the default ctor, it won't make any difference. It's just a wrapper around 
a static instance. This also has the unfortunate disadvantage of never 
reseeding.

The PRNG itself is based on an iterative hash function. While there are no 
obvious weaknesses of this, all hash functions (and block ciphers) exhibit some 
bias over large sets of data. Some countermeasures are already in place (one 
hash-based PRNG feeds another hash-based PRNG, which reseeds every so often 
from the first) but it's probably still advisable to reseed occasionally. 
Ideally you'd have a deep understanding of all the statistics and use a 
calculation to determine how often to reseed, but realistically, almost nobody 
has that level of depth, and it's all estimations anyway. So as a reasonable 
way of coming up with some estimate of how often to reseed, take for example 
Fortuna, which reseeds every 1MB, and is based on a block cipher that needs 
reseeding much more frequently (some orders of magnitude). In reality, even if 
you never reseed, you'll probably never encounter a problem, because as I said, 
countermeasures are already in place.

So if you're uber-paranoid, you would construct your own SecureRandom, and 
you'll have a separate one for each connection, each seeded with a new unique 
seed that you generated yourself, and you'll reseed periodically (which implies 
you'll need to keep a reference to "prng"), as follows.

var digest = new Org.BouncyCastle.Crypto.Digests.Sha256Digest();
var prng = new Org.BouncyCastle.Crypto.Prng.DigestRandomGenerator(digest);
byte[] newSeed;
newSeed = BitConverter.GetBytes(DateTime.Now.Ticks); // At most 8 to 14 bits, 
realistically maybe 4
prng.AddSeedMaterial(newSeed);
Array.Clear(newSeed, 0, newSeed.Length);
var tsg = new Org.BouncyCastle.Crypto.Prng.ThreadedSeedGenerator();
newSeed = tsg.GenerateSeed(640, fast: false); // Assuming 5% entropy, this is 
20x 32 bytes
prng.AddSeedMaterial(newSeed);
Array.Clear(newSeed,0,newSeed.Length);
// Similarly, add entropy from any additional sources available.
// If you feel like it, take a look at https://tinhatrandom.org
// In particular, the WindowsFormsMouse and WinFormsKeyboardInputPrompt
// And see List of Random Number Servers 
(http://en.wikipedia.org/wiki/List_of_random_number_generators#Random_Number_Servers)
var foo = new Org.BouncyCastle.Security.SecureRandom(prng);


> What I am observing is
> in the ThreadedSeedGenerator class, the DoGenerateSeed function is stuck
> in what appears to be an infinite loop as the Run method is never hit to
> increase the counter. 

That is indeed, bad news. I'm going to write a separate reply to it.

Reply via email to