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

Reply via email to