Files
JJBB/Assets/Plugins/Best HTTP/Source/SecureProtocol/crypto/prng/ThreadedSeedGenerator.cs
2024-08-23 15:49:34 +08:00

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