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;
}
}
}