I've been trying to write a simple helper method in C# that generates a cryptographically-secure random string with any given length and character set. I know that you shouldn't use the Random
class if you want cryptographic security. In the past, the RNGCryptoServiceProvider
class would always be suggested as an alternative to Random
to provide cryptographic safety. That class is now obsolete and RandomNumberGenerator
is supposed to be used instead.
Now, what I'm confused about is that many answers in this famous question that are using the new RandomNumberGenerator
class — such as this one — are using the GetBytes()
method, and then doing lots of other stuff afterwards to make things work; but I don't understand why they're not using GetInt32()
instead and then using the result as an index in the character set? It seems like that would make this much simpler.
This is what I'm talking about:
public string GenerateRandomString(int length, string charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
{
char[] result = new char[length];
for (int i = 0; i < length; i++)
result[i] = charSet[RandomNumberGenerator.GetInt32(charSet.Length)];
return new string(result);
}
My question is this: Is this way of generating random strings cryptographically sound or not? The fact that I never saw this being done makes me uncertain, which is why I'm asking this question. And if it isn't, could you please explain why?
Thank you.
From the documentation you have linked:
Cryptographic random number generators create cryptographically strong random values.
Okay, let's now look at GetInt32
:
Generates a random integer between 0 (inclusive) and a specified exclusive upper bound using a cryptographically strong random number generator.
(emphasis mine)
Most importantly, it later on states:
This method uses a discard-and-retry strategy to avoid the low value bias that a simple modular arithmetic operation would produce.
So it can be used to reliably produce a random string, yes.
As for the reasoning, well, RNGCryptoServiceProvider
did not have GetInt32
, it only had GetBytes
, so of course old code that used to use RNGCryptoServiceProvider
and was then hastily modified to use RandomNumberGenerator
instead to fix the obsolete warning won't use the new method.