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