Wednesday, April 14, 2010

Cryptographically Strong Random Number Generation With C#

In C# it's sometimes handy to be able to generate usable random numbers whether its for collision avoidance, security, generating realistic dummy data or just testing inputs. The problem is that using the built in .Net Random class several times in quick succession, although fast, will give you identical results for a given unit of execution time (assuming you are seeding with a time value, which most people seem to do).

Cryptographically Strong Random Number Generation
Computers do a lot of things well but randomness is not one of them. The .Net class System.Security.Cryptography.RNGCryptoServiceProvider is used to generate "random" numbers in a far more unpredictable sequence than the Random class (although still not truly random, but good enough.). Using RNGCryptoServiceProvider is far more computationally expensive than  using Random so you have to decide how important the actual randomness is in your project.

using System.Security.Cryptography;

public int GetRandomIntStrong(int min, int max)
{
    if ((min < 0) || (max < 0))
    {
        throw new ArgumentException("Arguments must be greater than or equal to zero.");
    }
    else if (max < min)
    {
        throw new ArgumentException("Argument max must be greater than min.");
    }

    // Create a byte array to hold the random value.
    //using 4 bytes = 32-bit integer
    byte[] randomNumber = new byte[4];

    // Create a new instance of the RNGCryptoServiceProvider.
    RNGCryptoServiceProvider gen = new RNGCryptoServiceProvider();

    // Fill the array with a random value.
    gen.GetBytes(randomNumber);

    // Convert the byte to an integer value
    int rand = Math.Abs(BitConverter.ToInt32(randomNumber, 0));

    // Apply the random number to the argument range
    return Math.Abs(min + (rand % (max - min + 1)));
}

No comments:

Post a Comment