Hey, cool project. I'd normally make a pull request for this, but this is really only a start (and not complete because BC doesn't have Windows Store project files).
I don't know if you are interested or not in building for Windows Phone/Store/etc, but attached are a very basic abstract RandomNumberGenerator class (no System.Security.Cryptography on Windows Phone/Store) and an alternate implementation of SystemRNGNumberGenerator that uses the Windows.Security.Cryptography APIs. Hope you find them useful, Jeff On Fri, Jul 18, 2014 at 4:43 PM, Edward Ned Harvey (bouncycastle) < bouncycas...@nedharvey.com> wrote: > > From: Edward Ned Harvey (bouncycastle) > > [mailto:bouncycas...@nedharvey.com] > > > > The default constructor of SecureRandom uses GetSeed(8), which is only 64 > > bits, but worse yet, GetSeed seeds itself from the system clock Ticks. > > 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. > > So I think this is actually ok. Yes it could be stronger, by additionally > pulling from things like the OS CryptoApiGenerator in addition to > ThreadedSeedGenerator and Ticks, but no, it's not a big bad problem as I > thought. Sorry again, and thanks for discussion... > >
using System; namespace tinhat { abstract class RandomNumberGenerator : IDisposable { ~RandomNumberGenerator () { Dispose (false); } public abstract void GetBytes (byte[] data); public abstract void GetNonZeroBytes (byte[] data); protected virtual void Dispose (bool disposing) { } public void Dispose () { Dispose (true); GC.SuppressFinalize (this); } } }
using System; #if NETFX_CORE using Windows.Security.Cryptography; #else using System.Security.Cryptography; #endif namespace tinhat.EntropySources { /// <summary> /// This is literally just a wrapper around System.Security.Cryptography.RNGCryptoServiceProvider, and adds no value /// whatsoever, except to serve as a placeholder in the "EntropySources" folder, so you remember to consider /// RNGCryptoServiceProvider explicitly as an entropy source. /// </summary> public sealed class SystemRNGCryptoServiceProvider : RandomNumberGenerator { #if NETFX_CORE public override void GetBytes (byte[] data) { if (data == null) throw new ArgumentNullException ("data"); int index = 0; while (index < data.Length) { uint rnd = CryptographicBuffer.GenerateRandomNumber (); int i = 0; while (i < 4 && index < data.Length) { data[index++] = (byte) (rnd & 0xFF); rnd >>= 8; i++; } } } public override void GetNonZeroBytes (byte[] data) { if (data == null) throw new ArgumentNullException ("data"); int index = 0; while (index < data.Length) { uint rnd = CryptographicBuffer.GenerateRandomNumber (); while (rnd != 0 && index < data.Length) { if ((rnd & 0xFF) != 0) data[index++] = (byte) (rnd & 0xFF); rnd >>= 8; } } } #else private RNGCryptoServiceProvider myRNG = new RNGCryptoServiceProvider(); private bool disposed = false; public override void GetBytes(byte[] data) { myRNG.GetBytes(data); } public override void GetNonZeroBytes(byte[] data) { myRNG.GetNonZeroBytes(data); } protected override void Dispose(bool disposing) { if (this.disposed) { return; } myRNG.Dispose(); base.Dispose(disposing); } ~SystemRNGCryptoServiceProvider() { Dispose(false); } #endif } }