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.Â
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.
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:
[Orderer(SummaryOrderPolicy.FastestToSlowest)] public class RandomNumberBenchmarks { [Benchmark] public int UsingCryptoSecureRandomNumberGenerator() => CryptographicHelpers.GenerateSecureRandomInteger(1, 100); [Benchmark] 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.
Conclusion
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.