RNGCryptoServiceProvider - Random Number Review
Don't use your code. Your solution is wrong and generates poor random numbers. I suggest my solution, which generates cryptographically strong random numbers:
public class SecureRandom : RandomNumberGenerator
{
private readonly RandomNumberGenerator rng = new RNGCryptoServiceProvider();
public int Next()
{
var data = new byte[sizeof(int)];
rng.GetBytes(data);
return BitConverter.ToInt32(data, 0) & (int.MaxValue - 1);
}
public int Next(int maxValue)
{
return Next(0, maxValue);
}
public int Next(int minValue, int maxValue)
{
if (minValue > maxValue)
{
throw new ArgumentOutOfRangeException();
}
return (int)Math.Floor((minValue + ((double)maxValue - minValue) * NextDouble()));
}
public double NextDouble()
{
var data = new byte[sizeof(uint)];
rng.GetBytes(data);
var randUint = BitConverter.ToUInt32(data, 0);
return randUint / (uint.MaxValue + 1.0);
}
public override void GetBytes(byte[] data)
{
rng.GetBytes(data);
}
public override void GetNonZeroBytes(byte[] data)
{
rng.GetNonZeroBytes(data);
}
}
Well, using RNGCryptoServiceProvider
gives you an unguessable crypto-strength seed whereas Environment.TickCount
is, in theory, predictable.
Another crucial difference would be evident when calling your NextInt
method several times in quick succession. Using RNGCryptoServiceProvider
will seed the Random
object with a different crypto-strength number each time, meaning that it will go on to return a different random number for each call. Using TickCount
risks seeding the Random
object with the same number each time (if the method is called several times during the same "tick"), meaning that it will go on to return the same (supposedly random) number for each call.
If you genuinely need truly random numbers then you shouldn't be using a computer to generate them at all: you should be measuring radioactive decay or something similarly, genuinely unpredictable.