149 lines
4.2 KiB
C#
149 lines
4.2 KiB
C#
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
|
#pragma warning disable
|
|
using System;
|
|
using System.Threading;
|
|
|
|
#if NO_THREADS || NETFX_CORE
|
|
using System.Threading.Tasks;
|
|
#endif
|
|
|
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
|
|
|
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Prng
|
|
{
|
|
/**
|
|
* A thread based seed generator - one source of randomness.
|
|
* <p>
|
|
* Based on an idea from Marcus Lippert.
|
|
* </p>
|
|
*/
|
|
public class ThreadedSeedGenerator
|
|
{
|
|
private class SeedGenerator
|
|
{
|
|
#if NETCF_1_0
|
|
// No volatile keyword, but all fields implicitly volatile anyway
|
|
private int counter = 0;
|
|
private bool stop = false;
|
|
#else
|
|
private volatile int counter = 0;
|
|
private volatile bool stop = false;
|
|
#endif
|
|
|
|
private void Run(object ignored)
|
|
{
|
|
while (!this.stop)
|
|
{
|
|
this.counter++;
|
|
}
|
|
}
|
|
|
|
public byte[] GenerateSeed(
|
|
int numBytes,
|
|
bool fast)
|
|
{
|
|
#if SILVERLIGHT || PORTABLE || NETFX_CORE
|
|
return DoGenerateSeed(numBytes, fast);
|
|
#else
|
|
ThreadPriority originalPriority = Thread.CurrentThread.Priority;
|
|
try
|
|
{
|
|
Thread.CurrentThread.Priority = ThreadPriority.Normal;
|
|
return DoGenerateSeed(numBytes, fast);
|
|
}
|
|
finally
|
|
{
|
|
Thread.CurrentThread.Priority = originalPriority;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
private byte[] DoGenerateSeed(
|
|
int numBytes,
|
|
bool fast)
|
|
{
|
|
this.counter = 0;
|
|
this.stop = false;
|
|
|
|
byte[] result = new byte[numBytes];
|
|
int last = 0;
|
|
int end = fast ? numBytes : numBytes * 8;
|
|
|
|
#if NO_THREADS || NETFX_CORE
|
|
Task.Factory.StartNew(() => Run(null), TaskCreationOptions.None);
|
|
#else
|
|
ThreadPool.QueueUserWorkItem(new WaitCallback(Run));
|
|
#endif
|
|
|
|
#if PORTABLE || NETFX_CORE
|
|
AutoResetEvent autoResetEvent = new AutoResetEvent(false);
|
|
#endif
|
|
|
|
try
|
|
{
|
|
for (int i = 0; i < end; i++)
|
|
{
|
|
while (this.counter == last)
|
|
{
|
|
try
|
|
{
|
|
#if PORTABLE || NETFX_CORE
|
|
autoResetEvent.WaitOne(1);
|
|
#else
|
|
Thread.Sleep(1);
|
|
#endif
|
|
}
|
|
catch (Exception)
|
|
{
|
|
// ignore
|
|
}
|
|
}
|
|
|
|
last = this.counter;
|
|
|
|
if (fast)
|
|
{
|
|
result[i] = (byte)last;
|
|
}
|
|
else
|
|
{
|
|
int bytepos = i / 8;
|
|
result[bytepos] = (byte)((result[bytepos] << 1) | (last & 1));
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
#if PORTABLE || NETFX_CORE
|
|
autoResetEvent.Dispose();
|
|
#endif
|
|
}
|
|
|
|
this.stop = true;
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generate seed bytes. Set fast to false for best quality.
|
|
* <p>
|
|
* If fast is set to true, the code should be round about 8 times faster when
|
|
* generating a long sequence of random bytes. 20 bytes of random values using
|
|
* the fast mode take less than half a second on a Nokia e70. If fast is set to false,
|
|
* it takes round about 2500 ms.
|
|
* </p>
|
|
* @param numBytes the number of bytes to generate
|
|
* @param fast true if fast mode should be used
|
|
*/
|
|
public byte[] GenerateSeed(
|
|
int numBytes,
|
|
bool fast)
|
|
{
|
|
return new SeedGenerator().GenerateSeed(numBytes, fast);
|
|
}
|
|
}
|
|
}
|
|
#pragma warning restore
|
|
#endif
|