Algorithm to generate secure number of fixed lenght with RNGCryptoServiceProvider

pampua84

New member
Joined
Mar 4, 2021
Messages
2
Programming Experience
3-5
Hi guys,
I'm looking for an algorithm to generate a safe random number like an OTP and I found this code on the web:

Secure Random Number Generator:
const int min = 100000;
const int max = 999999;
const int elemInRange = max - min + 1;

var randomData = new byte[4];

using var rng = new RNGCryptoServiceProvider();
rng.GetBytes(randomData);
var randomInt = BitConverter.ToUInt32(randomData, 0);
var mod = randomInt % elemInRange;

var secureNumber = min + mod;

The problem is that I completely understand how this can generate a 6 digit number, so I'm not sure it's correct and I can use it.
Can someone kindly explain to me how this algorithm works and if it is correct to generate a 6 digit number?

Thanks a lot
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,921
Location
Sydney, Australia
Programming Experience
10+
Have you tried to understand it? Have you read the documentation for the RNGCryptoServiceProvider class and its GetBytes method? Have you done the same for BitConverter.ToUInt32? Do you know what the % operator does? Once you understand all those things, have you stepped through the code line by line to see exactly what it does for yourself? I'm not saying that we can't or won't help but there's a lot you can do for yourself first that it doesn't look like you've done.
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
3,386
Location
Chesapeake, VA
Programming Experience
10+
Also, there's a small problem with the code presented above. Zero will never be a leading digit. So instead of of 10^6 possible values it'll be 9x10^5 values. (And yes, I've received codes with leading zeroes on both my phone authenticator as well as my RSA key fob.)
 

pampua84

New member
Joined
Mar 4, 2021
Messages
2
Programming Experience
3-5
Hello,
sorry, maybe I was not very clear in asking the question, the line
C#:
rng.GetBytes (randomData);
fills the 8 bytes (32bit) with random values
then
C#:
var randomInt = BitConverter.ToUInt32(randomData, 0);
it converts those random bytes to an unsigned int,
then
C#:
var mod = randomInt % elemInRange;
performs the division and gives me the rest of that operation.
Now what I don't understand is: rng fills those bytes with random values, but couldn't they also be all 0s except 1?
Wouldn't that result in transforming to an int 1?
Why divide
C#:
var mod = randomInt % elemInRange;
?
Couldn't I exceed 6 digits by adding the min value?
I hope I have been clearer on my doubts.
Thanks
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,921
Location
Sydney, Australia
Programming Experience
10+
maybe I was not very clear in asking the question
You weren't. If there's a section of code and you understand most of it but not one specific part then you need to specify that, because it's a waste of everyone's time for us to explain to you the parts that you already understand. Always be specific about exactly what problem you're trying to solve.

Anyway, after this:
C#:
const int min = 100000;
const int max = 999999;
const int elemInRange = max - min + 1;
the elemInRange constant will contain the difference between the min and max constants. This:
C#:
var mod = randomInt % elemInRange;
doesn't just do a division but gives you the remainder from that division. If you divide a number by elemInRange then the remainder will always be less than elemInRange. As a result, after this:
C#:
var secureNumber = min + mod;
secureNumber cannot be less than min and cannot be greater than max, i.e. it is a number in the specified range.
 
Top Bottom