123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- #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
|