public async Task ForceReseed() { var sources = new IEntropySource[] { new CryptoRandomSource(64), new CurrentTimeSource(), new GCMemorySource(), new TimerSource(), new UserSuppliedSource(CypherBasedPrngGenerator.CreateWithCheapKey().GetRandomBytes(2048)) }; var acc = new EntropyAccumulator(new StandardRandomWrapperGenerator()); var rng = PooledEntropyCprngGenerator.Create(sources, accumulator: acc, config: Conf()); Assert.AreEqual(rng.BytesRequested, 0); Assert.AreEqual(rng.ReseedCount, 0); Assert.AreEqual(rng.IsRunning, false); Assert.AreEqual(rng.EntropyPriority, EntropyPriority.High); Assert.AreEqual(rng.SourceCount, 5); await rng.StartAndWaitForFirstSeed(); Assert.IsTrue(rng.ReseedCount >= 1); Assert.IsTrue(acc.TotalEntropyBytes > 0); Assert.AreNotEqual(rng.EntropyPriority, EntropyPriority.High); var reseedCount = rng.ReseedCount; var entropy = acc.TotalEntropyBytes; await rng.Reseed(); Assert.IsTrue(rng.ReseedCount > reseedCount); Assert.IsTrue(acc.TotalEntropyBytes > entropy); await rng.Stop(); }
public async Task CreatePrngFromPooled() { var sources = new IEntropySource[] { new CryptoRandomSource(64), new CurrentTimeSource(), new GCMemorySource(), new TimerSource(), new UserSuppliedSource(CypherBasedPrngGenerator.CreateWithCheapKey().GetRandomBytes(2048)) }; var acc = new EntropyAccumulator(new StandardRandomWrapperGenerator()); var rng = PooledEntropyCprngGenerator.Create(sources, accumulator: acc, config: Conf()); Assert.AreEqual(rng.BytesRequested, 0); Assert.AreEqual(rng.ReseedCount, 0); Assert.AreEqual(rng.IsRunning, false); Assert.AreEqual(rng.EntropyPriority, EntropyPriority.High); Assert.AreEqual(rng.SourceCount, 5); await rng.StartAndWaitForFirstSeed(); Assert.IsTrue(rng.ReseedCount >= 1); Assert.IsTrue(acc.TotalEntropyBytes > 0); System.Threading.Thread.Sleep(1); // EntropyPriority is only updated after the reseed event, so it might not be current. Assert.AreNotEqual(rng.EntropyPriority, EntropyPriority.High); var prng = rng.CreateCypherBasedGenerator(); Assert.IsNotNull(prng); var bytes = prng.GetRandomBytes(16); Assert.IsFalse(bytes.All(b => b == 0)); await rng.Stop(); }
/// <summary> /// Creates a pooled random number generator that conforms to the Fortuna spec. /// This is more conservative than Terninger; no randomised pools or low priority mode. /// </summary> public static PooledEntropyCprngGenerator CreateFortuna() => PooledEntropyCprngGenerator.Create( initialisedSources: BasicSources(), accumulator: new EntropyAccumulator(32, 0), config: new PooledEntropyCprngGenerator.PooledGeneratorConfig() { // Set the ways to enter low priority mode so high they should never be hit. ReseedCountBeforeSwitchToLowPriority = Int32.MaxValue, TimeBeforeSwitchToLowPriority = TimeSpan.MaxValue, // Reseed more aggressively as well. MaximumBytesGeneratedBeforeReseed = 1024L * 1024L, MinimumTimeBetweenReseeds = TimeSpan.FromHours(1), } );
public async Task EventIsRaisedOnReseed() { var sources = new IEntropySource[] { new CryptoRandomSource(64), new CurrentTimeSource(), new GCMemorySource(), new TimerSource(), new UserSuppliedSource(CypherBasedPrngGenerator.CreateWithCheapKey().GetRandomBytes(2048)) }; var acc = new EntropyAccumulator(new StandardRandomWrapperGenerator()); var rng = PooledEntropyCprngGenerator.Create(sources, accumulator: acc, config: Conf()); Object setInReseedEvent = null; rng.OnReseed += (o, e) => setInReseedEvent = new object(); Assert.AreEqual(rng.BytesRequested, 0); Assert.AreEqual(rng.ReseedCount, 0); Assert.AreEqual(rng.IsRunning, false); Assert.AreEqual(rng.EntropyPriority, EntropyPriority.High); Assert.AreEqual(rng.SourceCount, 5); await rng.StartAndWaitForFirstSeed(); Assert.IsNotNull(setInReseedEvent); await rng.Stop(); }
public async Task GetFirstSeed_MixedSyncAndAsyncSources() { var sources = new IEntropySource[] { new CryptoRandomSource(32), new CurrentTimeSource(), new GCMemorySource(), new TimerSource(), new AsyncCryptoRandomSource(), new ProcessStatsSource(), new NetworkStatsSource() }; var acc = new EntropyAccumulator(new StandardRandomWrapperGenerator()); var rng = PooledEntropyCprngGenerator.Create(sources, accumulator: acc, config: Conf()); Assert.AreEqual(rng.BytesRequested, 0); Assert.AreEqual(rng.ReseedCount, 0); Assert.AreEqual(rng.IsRunning, false); Assert.AreEqual(rng.EntropyPriority, EntropyPriority.High); Assert.AreEqual(rng.SourceCount, 7); await rng.StartAndWaitForFirstSeed(); Assert.IsTrue(rng.ReseedCount >= 1); Assert.IsTrue(acc.TotalEntropyBytes > 0); System.Threading.Thread.Sleep(1); // EntropyPriority is only updated after the reseed event, so it might not be current. Assert.AreNotEqual(rng.EntropyPriority, EntropyPriority.High); await rng.Stop(); }
public async Task FirstSeedYieldsDifferentBytes() { var sources = new IEntropySource[] { new CryptoRandomSource(64), new CurrentTimeSource(), new GCMemorySource(), new TimerSource(), new UserSuppliedSource(CypherBasedPrngGenerator.CreateWithCheapKey().GetRandomBytes(2048)) }; var acc1 = new EntropyAccumulator(new StandardRandomWrapperGenerator()); var rng1 = PooledEntropyCprngGenerator.Create(sources, accumulator: acc1, config: Conf()); await rng1.StartAndWaitForFirstSeed(); var acc2 = new EntropyAccumulator(new StandardRandomWrapperGenerator()); var rng2 = PooledEntropyCprngGenerator.Create(sources, accumulator: acc2, config: Conf()); await rng2.StartAndWaitForFirstSeed(); var bytesFrom1 = rng1.GetRandomBytes(64); Assert.IsFalse(bytesFrom1.All(b => b == 0)); var bytesFrom2 = rng2.GetRandomBytes(64); Assert.IsFalse(bytesFrom2.All(b => b == 0)); // Expect two generates with different inputs will give different bytes from from the start. Assert.IsFalse(bytesFrom1.SequenceEqual(bytesFrom2)); await rng1.Stop(); await rng2.Stop(); }
/// <summary> /// Creates a pooled random number generator that makes improvements and changes to the Fortuna spec. /// This allows for less CPU usage, uses randomised pools, but isn't "official". /// </summary> public static PooledEntropyCprngGenerator CreateTerninger() => PooledEntropyCprngGenerator.Create( initialisedSources: BasicSources(), accumulator: new EntropyAccumulator(16, 16, CypherBasedPrngGenerator.CreateWithCheapKey()) );