Return to HomePage



Generating Cryptographically Secure Random Numbers (C#)


Applies to

* .NET Framework 2.0
* C#

Summary

The purpose of this code snippet is to illustrate how to generate cryptographically secure random numbers for a variety of applications using .NET. Possible uses of cryptographically-secure random numbers are session identifiers, encryption key material and default or auto-generated passwords.

Objectives

* Create a random number value whose value cannot be utilized to determine subsequent number values generated by the same function


Scenarios

* Create an "un-guessable" session identifier or application cookie for customized session management
* Create a one-time-use number for use as a second authentication factor, such as an argument for use within a forgotten email password
* Create an arbitrary default secret, such as a default password, from random data

Solution Example

static public int SecureRandomNumber()
{
		    		// Create a secure RNG class and a byte array to hold the random data
		    		[RNGCryptoServiceProvider] secureRandom = new [RNGCryptoServiceProvider();]
		    		byte[] randBytes = new byte[4];
	

		    		// Generate 4 bytes of secure random number data and convert to 4-byte integer
		    		[secureRandom.GetNonZeroBytes(randBytes);]
		    		[return(BitConverter.ToInt32(randBytes,] 0));
	
}


Problem Example

The following example shows generation of a random number using the
System.Random class.

static public int UnsecureRandomNumber(int seed)
{
		    		// Creates a random number, using the default machine time-derived seed 
		    		Random unsecureRandom = new Random(seed);
		    		return(unsecureRandom.Next());
	
}

* Same seed value will always return the same sequence of numbers
* Seed value -1 or null will make use of machine time to generate seed, which is easily predicted

Test Case

The following classes must be included in any project making use of the sample code provided above:

using System.Security.Cryptography;

Run the following code to generate a set of both unsecure and secure random numbers. The unsecure example illustrates that two calls to Random that make use of the same seed will return the same sequence of numbers.

static void Main(string[] args)
{
		    		// Unsecure Random Number
		    		Console.WriteLine("Unsecure Value, Default Seed: " + [UnsecureRandomNumber(-1));]
		    		Console.WriteLine("Unsecure Value, Default Seed: " + [UnsecureRandomNumber(-1));]
		    		Console.WriteLine("Unsecure Value, Seed = 100: " + [UnsecureRandomNumber(100));]
		    		Console.WriteLine("Unsecure Value, Seed = 100: " + [UnsecureRandomNumber(100));]
		    		Console.WriteLine("");
	

		    		// Secure Random Numbers
		    		for(int i = 0; i < 10; i++) {
		        			Console.WriteLine("Secure Value, no seed: " + [SecureRandomNumber());]
		    		}
	
}

static public int UnsecureRandomNumber(int seed)
{
		    		// Creates a random number, using the default machine time-derived seed 
		    		Random unsecureRandom = new Random(seed);
		    		return(unsecureRandom.Next());
	
}


Expected Result

Unsecure Value, Default Seed: 534011718
Unsecure Value, Default Seed: 534011718
Unsecure Value, Seed = 100: 2080427802
Unsecure Value, Seed = 100: 2080427802

Secure Value, no seed: 1392122031
Secure Value, no seed: -1635401565
Secure Value, no seed: 1863340408
Secure Value, no seed: -497957136
Secure Value, no seed: -1444637226
Secure Value, no seed: 925340612
Secure Value, no seed: 92412438
Secure Value, no seed: -1126434204
Secure Value, no seed: 2086044763
Secure Value, no seed: -840759923


Additional Resources

* Generating Random Keys (.NET): http://msdn.microsoft.com/library/en-us/dnpag2/html/PAGGuidelines0003.asp?frame=true#pagguidelines0003_crypto3
* RNGCryptoServiceProvider Class: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemsecuritycryptographyrngcryptoserviceproviderclasstopic.asp


Attributes

* Applies To: .NET Framework 2.0, C#
* Category: Cryptography
* Author: Jonathan Bailey





Return to HomePage
Microsoft Communities