1. Technology

How to use random numbers in Visual Basic .NET programs

Getting Really Random - RNGCryptoServiceProvider

By

According to Microsoft, "Computers cannot generate truly random numbers. Instead, they return a series of numbers based on a mathematical relationship that simulates 'randomness.' The 'randomness' exhibited by the numbers is a function of the mathematical formula used by the random number generator."

The legendary computer pioneer John Von Neumann put it more simply, "Anyone who considers arithmetic methods of producing random digits is, of course, in a state of sin." So if your application requires real random numbers, you need something hardware based. If you want to read the nitty-gritty on that, knock yourself out: The Intel Random Number Generator.

But computers can get dang close to 'truly random numbers' and if you've got the need, VB.NET has the code. That's what the RNGCryptoServiceProvider object in System.Security.Cryptography provides. (A note on terminology, many pages use the acronym PRNG without explaining it. That's "Pseudo Random Number Generator" and it means that the number is based on a computer algorithm so it's not actually random.)

Before getting into details, let me make one disclaimer. I am not a crypto expert or a mathematician. In previous articles brushing up against subjects like this, I have discovered that there are people who live and breath in their own rarefied specialization and they love to pounce on any error. To all of those, I apologize in advance; and I also welcome your input and corrections. To the rest of you, my goal is to provide an explanation that makes this subject understandable and especially, programmable. If I get that much done, I'll die happy.

Like many Microsoft implementations, RNGCryptoServiceProvider is really just part of a more comprehensive architecture that is designed for future expansion. It inherits from a class called RandomNumberGenerator that provides basic functions. (RandomNumberGenerator can't be used by itself.) The idea is that future "providers" will become available, possibly from other vendors. But for now, RNGCryptoServiceProvider is the only one.

Microsoft appears to have done a thorough job of making RNGCryptoServiceProvider as secure as possible. Randomness is provided using various system and user data such as the process ID, thread ID, system clock, system time, system counter, memory status, free disk clusters, and hashed user environment block along with international standard cryptography algorithms. If that seems like a lot of processing, it is. That's one reason you probably should use the Random object instead unless you have a real need.

The syntax for using the RNGCryptoServiceProvider object is quite different again. The basic syntax generates a byte array, not a number. The Random object discussed above also has the NextBytes method - used in the Microsoft example quoted - that also creates a byte array. The code to use RNGCryptoServiceProvider might look like this:

Dim MyByteArray As Byte() = New Byte(100) {}
Dim MyRandom As New RNGCryptoServiceProvider()
MyRandom.GetBytes(MyByteArray)

The length of the byte array determines how many cryptographically strong random bytes are produced. So, to generate one 32 bit integer, this code will do the trick:

Dim ByteArray As Byte() = New Byte(3) {}
Dim rnd As New RNGCryptoServiceProvider()
rnd.GetBytes(ByteArray)
Dim myInteger As Integer = CStr(BitConverter.ToInt32(ByteArray, 0))

If your application requires non-zero random numbers, there's a separate method for that too (to preserve the cryptographic integrity of the object):

MyRandom.GetNonZeroBytes(MyByteArray)

There's actually one more way to generate random numbers favored by a few programmers and that is to create a GUID - a "Globally Unique Identifier". These numbers are the ones used to identify objects in the Registry. (Use 'Find' to search for 'CLSID' in Regedit to see as many examples as you want.) VB.NET can generate a GUID this way:

Dim myGUID As String = _
   (System.Guid.NewGuid().ToString()). _
   Replace("-", String.Empty)

The Replace method is there because NewGuid creates a string with hyphens in it. On my computer, this code created a string like this:

60c8f86131ec4b1abf72dc90dbf30991

Using this method is not a good idea. This is actually a serious problem since I found a lot of references that recommend it on pages that I otherwise would have trusted a lot. It makes me wonder how many programs exist out there that have serious security holes in them because the programmer thought a GUID was a cryptographically secure random number. It's not.

A GUID is a standardized identifier that is actually unique only when the whole thing is used. If you read the GUID standard (actually, called UUID in the standard and GUID by Microsoft) you will see that the parts of a GUID are actually well known and based on specific identifiers (such a four bit code in a specific position that tells you what kind of GUID it is). If you just use a substring you lose the uniqueness and certainly the randomness. You could end up with the same number every time if you were really unlucky. And the only applications that can use the entire GUID probably need a GUID, not just a random number.

  1. About.com
  2. Technology
  3. Visual Basic
  4. Using VB.NET
  5. Demystifying Random Numbers - Interpreting the Microsoft Doc

©2014 About.com. All rights reserved.