> From: Sid Shetye [mailto:sid...@outlook.com]
> 
> Also, the default used in
> SecureRandom() uses SHA1 internally - something we're not allowed to use
> anymore.

SHA1 has been shown to have some weaknesses in terms of collision resistance.  
(No collisions yet found, but SHA1 can no longer be considered a full strength 
hashing algorithm.)

SHA1 is still ok to use as the basis for a PRNG.


> Code (don't use this in production!)

The answer is simply as you said - Don't do that.

The problem is, you're passing your DigestRandomGenerator directly into 
SecureRandom, without keeping any reference to the DigestRandomGenerator.  It 
is therefore impossible for you to add any seed to it.

You *need* to keep a reference to the DigestRandomGenerator, and you *need* to 
generate a seed somehow, that you'll add to it.

If you do that, you'll have a good strong secure prng.


> Talking of ThreadedSeedGenerator() (and with no disrespect to anyone
> here!), isn't it just a counter inside a constant time-periodic timer? 

Sort of, not really.

Let's first hypothetically suppose you have a single processor system.  One 
thread goes into a tight loop incrementing a counter.  Another thread goes into 
a loop sampling that counter.  Depending on when the thread scheduler 
interrupts the thread, you will sometimes see the same value twice and then 
sleep 1ms, or you will get paused and resume, seeing a different value. 

Thread scheduling depends on all the other processes and hardware interrupts 
happening in the system.  So all those things come into play and interfere with 
your output in unpredictable ways.

It gets a little more complicated in multiprocessor systems - because you may 
have one thread looping and incrementing while another thread simultaneously 
runs on another processor sampling the counter.  You still have all the 
interactions of the system other processes and hardware interrupts...  But you 
also have L1, L2, L3 cache misses, and memory bus contention to push the 
updated memory out to RAM.  And all of this is different if your multiple 
threads happen to run on a hyperthreaded single core, versus executing on truly 
separate cores, versus executing on separate cores that are also in separate 
sockets.


> (RDRAND which sources from diode thermal
> noise for a True-RNG seed). 

It's actually ironic that you mention RDRAND, as this has been the center of a 
lot of controversy lately.  And when I give talks about TinHat Random, and 
distrust for the OS crypto random generator, I use RDRAND as the showpiece for 
*why* you should distrust it.

If done right, RDRAND should be very good and very effective.  It should 
contribute entropy to the OS crypto random generator, and then the OS crypto 
random generator should be absolute best, fastest, strongest RNG available.  
However, there are several reasons this is not always the case:

NSA reports of Intel tampering with the doping of the semiconductor, to reduce 
the entropy to an arbitrary number of bits (32) instead of the 128 it's 
supposed to provide.  Linus included a patch that lets the RDRAND entropy 
bypass the OS kernel hashing, so it gets fed directly to userland.  This 
happened over Matt Mackall's insistent complaints (the security maintainer at 
the time) which led to Matt's resignation as protest.

I can say a lot more, including discussion of what mono does behind the scenes 
in RNGCryptoServiceProvider, but I'm going to drop the discussion short, and 
just say this:  

The OS crypto RNG should be the best thing going for you.  The only way it's 
not is when the kernel does something nefarious or incompetent (MS, Apple, and 
many others closed source, while even Linux kernel crypto RNG, which is open 
source, has known vulnerabilities as well as shrouded in controversy.)  

So if there's anything wrong with your OS crypto RNG, it's either because (a) 
the kernel intentionally weakens the RNG, or (b) the kernel uses hardware that 
weakens the RNG.  Either way, the only people you can distrust are the hardware 
and kernel manufacturers.

As long as you use the OS crypto RNG, you have strong random relative to 
everyone else.  The only thing you then need to be concerned about is finding 
some random source that cannot be hacked by the hardware and kernel 
manufacturers.  This is the reason for TinHat Random to exist.  It's designed 
specifically for this purpose.

You don't need to sample hardware random directly - as it is already included 
in the OS crypto RNG.  You only need to sample the OS crypto RNG, and also 
sample something else that the OS and hardware manufacturers couldn't possibly 
have compromised.


> Finally, you're right about the SetSeed(). But that doesn't help the fact that
> the RNGs can still produce identical sequences and that the seed isn't very
> strong.

I specifically *need* that functionality.  I use BouncyCastle 
DigestRandomGenerator as the basis for CBCrypt.  http://www.cbcrypt.org
The requirement of CBCrypt is:  If you enter the same password twice on 
different machines at different times, then it will generate the same 
public/private keypair deterministically.  In order to do this, I require a 
PRNG which can be seeded with a specific value and have absolutely no 
randomness in it, other than the secret password that was entered.

Both what's great, and what's bad, about BouncyCastle, is that the API is so 
low level.  You can do all sorts of good things - and bad things.  You have to 
really pay attention to what you're doing.  You don't need to be a crypto 
expert, but you should have at least one or a few classes on how to use crypto 
correctly, or else you'll shoot yourself in the foot.

Reply via email to