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) <
[email protected]> wrote:
> > From: Edward Ned Harvey (bouncycastle)
> > [mailto:[email protected]]
> >
> > 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
}
}