# (Don't be) Insecure Randomness

The OWASP Foundation identifies Randomness as potentially insecure. You can read more about it  [here](https://owasp.org/www-community/vulnerabilities/Insecure_Randomness).

#### So, Random generators are insecure?
In a nutshell, yes! - the general concept is that when you ask your underlying code framework (C# / Java / whatever) to generate a random number (i.e. ```new Random().Next()```) it's not as random as you would think. Without getting into too much detail, by default they tend to use a ***statistical*** Pseudo-Random Number Generator (PRNG). 

#### I might need a little more detail...?
The problem is that when you string together several random values (i.e. when generating a key of some sort) - that ***stream*** of random values is considered ***statistically*** 'highly predictable'.  Maybe not so predictable by yours truly, but I'm sure with enough hours we could throw together an app to prove this. 

*Anyway*, let's accept that OWASP is right, and statistical random number generation is bad practice if you want to stay secure. Who knows where that utility function you wrapped up will be used over the years? Maybe in some really sensitive areas.

#### So what do we do...?
Well, instead of using a ***statistical*** PRNG, we want to use a ***cryptographical*** one. In .NET Framework / .NET Core this is pretty easy to do with the ```System.Security.Cryptography.RandomNumberGenerator``` class. The thing about this class is that, out of the box, it's best at providing random ```byte[]``` data.

So, let's get a cryptographically random ```byte[]``` and use that to get an 
```Int32``` using the ```BitConvertor``` utility like so:
```
// Compliant for security-sensitive use cases
var randomGenerator = RandomNumberGenerator.Create(); 
byte[] data = new byte[16];
randomGenerator.GetBytes(data);
return BitConverter.ToInt32(data);
```

We can do the same to generate a ```double``` by simply using the ```ToDouble``` method on the ```BitConvertor```:
```
return BitConverter.ToDouble(data, 4);
```

#### What about random strings?
Well, you can use our randomly generated byte stream to *select* characters. Be warned, this does lessen the randomness somewhat. In the example below I am only selecting from one of 52 different characters, where each random byte could be one of 128 different values.

```
char[] chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
byte[] data = new byte[4 * length];

// Compliant for security-sensitive use cases
var randomGenerator = RandomNumberGenerator.Create(); 
randomGenerator.GetBytes(data);
StringBuilder result = new StringBuilder(length);
for (int i = 0; i < length; i++)
{
    var rnd = BitConverter.ToUInt32(data, i * 4);
    var idx = rnd % chars.Length;
    result.Append(chars[idx]);
}
return result.ToString();
```
Maybe if I just extended the char array to 128 different values that wouldn't be the case? I am certainly no  [David Zuckerman](https://www.cs.utexas.edu/~diz/) so I'd certainly be interested to hear from any die-hard crypto experts as to if my random guess (pun intended) is anywhere near mathematical reality??

#### Happy hacking!!!
