> 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.