Random vs RNGCryptoServiceProvider: Know your RNGs

28. July 2006 04:24

I have been doing some work with random number generation this week.  Specifically, I needed to write a utility that would be used to generate a strong key for a symmetric encryption algorithm.  Obviously, there is a wide variety of approaches to this type of task.  For my solution, I am using the RNGCryptoServiceProvider to randomize a position in an array of allowed characters.  While working on the solution, it made me start to wonder how often people may inappropriately use the Random class for random number generation.  I'm sure this topic has already been covered more than a few times, but I am going to throw in my two cents as well.

It is important to understand why Random can cause you grief.  The randomization is based on a deterministic mathematical algorithm.  If you supply the same seed, it will always generate the same sequence of numbers.  In an effort to minimize this risk, it is a common practice to use a date and/or time based value as the seed.  When possible, a single instance should be re-used rather than instantiating a new instance each time a random number needs to be generated.  This is for two reasons.  First, there is an increased risk of generating duplicate numbers when a new instance is used each time.  This is most obvious when generating a large quantity of numbers within a brief period of time (less than a second).  Second, re-using the instance achieves better performance since there is less overhead involved with a single instance. 

Consider the following snippets of code. 

// Duplicate Numbers...here we come!
for (int i = 0; i < 100; i++)
{
   Random rnd = new Random(); 
   int randomNumber = rnd.Next();
   Console.WriteLine("Generated {0} at {1}", randomNumber.ToString(), DateTime.Now.TimeOfDay.ToString());
   // Some processing happens here
}


// Ah...this looks much better!
Random rnd = new Random();
for (int i = 0; i < 100; i++)
{
   int randomNumber = rnd.Next();
   Console.WriteLine("Generated {0} at {1}", randomNumber.ToString(), DateTime.Now.TimeOfDay.ToString());
   // Some processing happens here
}

Now, don't get me wrong.  The Random class certainly is useful for practical randomization.  For example, randomizing the order of images for an image rotator could be a good scenario for possibly using the Random class.  However, if you need random numbers for the purpose of a generating a password or key, then you are much better served by using a class such as RNGCryptoServiceProvider or another class derived from RandomNumberGenerator.  These classes implement a cryptographic algorithm for creating strong random values. 

The moral of the story is that all random number generators are not created equal.  Be sure to comprehend the differences between them.  In doing so, you will be better equipped to make a decision of which one to use based upon your requirements.

Comments are closed

About Me

I'm a passionate software developer and advocate of the Microsoft .NET platform.  In my opinion, software development is a craft that necessitates a conscious effort to continually improve your skills rather than falling into the trap of complacency.  I was also awarded as a Microsoft MVP in Connected Systems in 2008, 2009, and 2010.


Can’t code withoutThe best C# & VB.NET refactoring plugin for Visual Studio
Follow jeff_barnes on Twitter

View Jeff Barnes's profile on LinkedIn

 

Shared Items

Disclaimer

Anything you read or see on this site is solely based on my own thoughts.  The material on this site does not necessarily reflect the views of my employer or anyone else.  In other words, I don't speak for anyone other than myself.  So, don't assume I am the official spokesperson for anyone.