In this article, we’ll explore how to generate random cryptographic numbers with RandomNumberGenerator API in C#, and why it is paramount in the context of cryptography. 

To download the source code for this article, you can visit our GitHub repository.

Let’s begin!

Overview of Cryptography

Cryptography is the practice of securing information and communications so that only authorized parties can access it. It uses encryption, decryption, and hashing techniques to protect the confidentiality and integrity of messages passing over the communications channel. The System.Security.Cryptography namespace within the .NET BCL provides robust support for cryptography APIs.

Next, grasping the significance of generating random numbers in cryptographic algorithms is crucial, so let’s explore that.

Importance of Random Numbers in Cryptography

Most cryptographic algorithms need a source of random data to generate new keys. Since most computers do not have a hardware-based random number generator, the program will use software-based techniques to generate random numbers as best.

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!

These random numbers are rarely truly random because software generates them. They are typically pseudorandom, meaning they appear random but are not. The System.Random API also has this problem.

Next, let’s look at the problems with the System.Random API.

Problems With the System.Random API

In .NET, we generally use the System.Random API when we need to generate a pseudorandom number.

This number generator provides the seed value when the object is in construction. This is fine for most application scenarios like games and will appear random.

However, this API is insufficient when implementing tight security because it is deterministic and predictable. The current implementation of  System.Random is based on a subtractive random number generator algorithm, which calculates a sequence of random numbers.

Still, each number is congruent to subtracting the previous two numbers from the sequence. So, we know this API is useless for creating cryptographic secure random numbers.

Now, let’s delve into security implications in the context of cryptography.

RandomNumberGenerator vs. System.Random for Cryptography

The RandomNumberGenerator class is used for number generators specifically designed for cryptographic purposes. Its platform-specific algorithm implementations produce unpredictable numbers with high entropy (the measure of randomness, the more the better), making it suitable for key generation and cryptographic operations.

This high entropy is achieved by not relying on the seed value but using system-level entropy sources like system time, mouse movements, or other unpredictable events. In contrast, the System.Random is a general-purpose number generator unsuitable for cryptographic operations due to its lower entropy and deterministic algorithm. Therefore, we can classify these number generators into CryptoSecureRandom and GeneralPurposeRandom.

Generate Secure Random Numbers With RandomNumberGenerator API

Let’s take a look at how we can use the RandomNumberGenerator class:

public static byte[] GenerateSecureRandomKey(int bytesCount) => RandomNumberGenerator.GetBytes(bytesCount);

Here, we create a GenerateSecureRandomKey() method that calls the RandomNumberGenerator.GetBytes() method. This method generates a random byte array of the specified length. Then, we can convert this byte array into a Base64 string. 

Let’s see another example of generating a random integer value based on the range provided:

public static int GenerateSecureRandomInteger(int minValue, int maxValue) => RandomNumberGenerator.GetInt32(minValue, maxValue);

By using the GetInt32() method, we generate a random integer value that falls in the predefined range.

Performance Comparison of System.Random and RandomNumberGenerator

To verify that RandomNumberGenerator is slower than System.Random, let’s set up benchmark tests to measure the speed of generating random integers:

public class RandomNumberBenchmarks
    public int UsingCryptoSecureRandomNumberGenerator() => 
        CryptographicHelpers.GenerateSecureRandomInteger(1, 100);

    public int UsingGeneralRandomNumberGenerator() => 
        CryptographicHelpers.GenerateGeneralRandomInteger(1, 100);

We are testing the GetInt32() method in the RandomNumberGenerator class and the Next() method in System.Random class. Benchmark tests were conducted by using the System.Random.Shared instance.

Now, let’s compare the speed performance of the crypto-secure random number generator (RandomNumberGenerator) with the general-purpose random number generator (System.Random):

| Method                                 | Mean      | Error    | StdDev   |
|--------------------------------------- |----------:|---------:|---------:|
| UsingGeneralRandomNumberGenerator      |  11.88 ns | 0.245 ns | 0.229 ns |
| UsingCryptoSecureRandomNumberGenerator | 154.58 ns | 1.916 ns | 1.793 ns |

The tradeoff in this approach is that RandomNumberGenerator is much slower to execute than System.Random. However, you make a minimal tradeoff when you generate numbers to use as encryption keys.


So, we learned how to create cryptographic numbers with RandomNumberGenerator API in C#. While both RandomNumberGenerator and System.Random have their places in .NET; understanding their differences is crucial. By choosing the right class for the right job, we can ensure security and efficiency in our applications.

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!