summary refs log tree commit diff
path: root/Crypto/src/crypto/prng/ThreadedSeedGenerator.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Crypto/src/crypto/prng/ThreadedSeedGenerator.cs')
-rw-r--r--Crypto/src/crypto/prng/ThreadedSeedGenerator.cs99
1 files changed, 99 insertions, 0 deletions
diff --git a/Crypto/src/crypto/prng/ThreadedSeedGenerator.cs b/Crypto/src/crypto/prng/ThreadedSeedGenerator.cs
new file mode 100644

index 000000000..9f918ea6e --- /dev/null +++ b/Crypto/src/crypto/prng/ThreadedSeedGenerator.cs
@@ -0,0 +1,99 @@ +using System; +using System.Threading; + +namespace 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) + { + this.counter = 0; + this.stop = false; + + byte[] result = new byte[numBytes]; + int last = 0; + int end = fast ? numBytes : numBytes * 8; + + ThreadPool.QueueUserWorkItem(new WaitCallback(Run)); + + for (int i = 0; i < end; i++) + { + var waitEvent = new ManualResetEvent(false); + + while (this.counter == last) + { + try + { + waitEvent.WaitOne(1); + } + 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)); + } + } + + 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); + } + } +}