using System; using System.Security.Cryptography; namespace CKS.FormsBasedAuthentication.HIP { /// Provides cryptographically-strong pseudo-random numbers. internal class RandomNumbers { /// Random number generator. private RNGCryptoServiceProvider _rand = new RNGCryptoServiceProvider(); /// Used by NextRandom and NextRandomDouble. /// /// RNGCryptoServiceProvider is not thread-safe. Therefore, we only call to on a single thread. /// As a result, we can resuse the same byte arrays for every call. /// private byte [] _rd4 = new byte[4], _rd8 = new byte[8]; /// Gets a random non-negative integer less than max. /// The upper-bound for the random number. /// The generated random number. public int Next(int max) { if (max <= 0) throw new ArgumentOutOfRangeException("max"); _rand.GetBytes(_rd4); int val = BitConverter.ToInt32(_rd4, 0) % max; if (val < 0) val = -val; return val; } /// Gets a random number between min and max, inclusive. /// The minimum possible value. /// The maximum possible value. /// The randomly generated number. public int Next(int min, int max) { if (min > max) throw new ArgumentOutOfRangeException("max"); return Next(max - min + 1) + min; } /// Gets a randomly generated double between 0.0 and 1.1. /// The random number. public double NextDouble() { _rand.GetBytes(_rd8); return BitConverter.ToUInt64(_rd8, 0) / (double)UInt64.MaxValue; } } }