Random numbers are everywhere on the web, and your security depends on them. Let’s see if you’re using them right.

Random numbers play a critical role in web application security. They are used in session identifiers, passwords, cryptographic keys, and more. However, if not implemented securely, they can lead to vulnerabilities that attackers can exploit to gain unauthorized access to sensitive information.

## TLDR

- Most random generators are not really random. They use math that looks random
- Do not use
`Math.random()`

in JavaScript or`random`

in Python - Use
`Web Crypto API`

in JavaScript,`crypto`

module in NodeJs, and`secrets`

in python - Do not try to implement your own random generation algorithm
- Incorrect usage of secure random numbers can make your application vulnerable

## How Random Functions work

There are two main types of Random Number Generators (RNGs): pseudo-random number generators (PRNGs) and true random number generators (TRNGs).

### Pseudo-random Number Generators (PRNGs)

PRNGs are the most commonly used type of RNGs. They work by using an algorithm to generate a sequence of numbers that appear to be random. The algorithm takes an initial value as input and produces a series of numbers based on it.

The common algorithms used in PRNGs are the Mersenne-Twister and linear congruential generator (LCG).

These algorithms get an initial number called `seed`

. They change it by adding previous random number, shifting, and doing XOR operators to generate the output. The output looks like a random number though it’s just an output of a formula.

If you keep executing any PRNG, it will eventually generate the same numbers over and over. Any PRNG has a fixed length of numbers that can generate before starting over.

### True Random Number Generators (TRNGs)

TRNGs generate truly random numbers based on physical processes that are inherently random. These processes include atmospheric noise, radioactive decay, and thermal noise. TRNGs measure the physical process and convert it into a random number.

## Random Function Vulnerabilities

The seed and random number generation algorithm both can have weaknesses.

### Prediction

You can say predictability is the main vulnerability of weak random number generators. PRNGs are inherently predictable as they are based on a mathematical formula. So if you know the seed and last random number, you can predict the next random number. This can lead to severe vulnerabilities.

For example, consider a forget password functionality that words based on a random token. If the token can be predicted, an attacker can reset the password of any user.

### Collision

Besides the predictability, Some random generators that have low quality produce duplicate values very often. This can increase the risk of collision.

Consider an application that generates random session tokens for its users. The chances of producing duplicate session tokens are related to two factors:

- Size of random space (length of session token)
- Quality of the random selection

Short-length tokens will have a higher chance of collisions. And bad random generator does not generate all possible values. This can lead to vulnerabilities where a user can see another user’s data.

### Seed Leakage or Manipulation

Another vulnerability related to random number generators is choosing a weak seed. PRNG always generates the same sequence of numbers with the same initial seed value. If an attacker can find the used seed or manipulate it, he can easily generate same random numbers.

In pratice, hackers use different methods to predict the next random number. Some methods may involve statistical analysis, while others may involve reverse-engineering the generator’s algorithm.

## How to Use Secure Random Numbers

Using cryptographically secure random number generation algorithms is the key to securely producing random numbers. These algorithms generate random numbers that are unpredictable and cannot be easily guessed by attackers. The output of these algorithms is resistant to brute-force attacks, and it’s statistically robust. You should not try to implement your own one unless you know what you are doing. Instead, always use known to be secure random libraries.

Let’s see a few examples of using secure random libraries in different programming languages.

### Javascript

The `Math.random()`

function is not suitable for cryptographic purposes, as it is not truly random and can be predicted or manipulated by an attacker.

To generate a secure random number in JavaScript, you can use the `Web Crypto API`

. The `Crypto.getRandomValues()`

method lets you get cryptographically strong random values. Here is an example code that generates a secure random number:

```
function generateRandomNumber() {
const array = new Uint32Array(1); // Create a 32-bit unsigned integer array
window.crypto.getRandomValues(array); // Fill the array with random values
return array[0]; // Return the first element of the array as the random number
}
console.log(generateRandomNumber()); // Output a random number between 0 and 4294967295
```

### NodeJS

In NodeJS, the `crypto`

module can be used to generate cryptographically secure random numbers. The following code sample illustrates the use of crypto module in generating a random number:

```
const crypto = require('crypto');
function generateRandomNumber() {
const randomBytes = crypto.randomBytes(4); // Generate 4 random bytes
const hexValue = randomBytes.toString('hex'); // Convert the bytes to a hex string
const intValue = parseInt(hexValue, 16); // Convert the hex string to an integer
return intValue;
}
console.log(generateRandomNumber()); // Output a random number between 0 and 4294967295
```

### Python

In Python, the `random`

module can be used to generate random numbers. However, it is not cryptographically secure. Instead, you can use the `secrets`

module to generate cryptographically secure random numbers. The following code sample illustrates the use of secrets module in generating a random number:

```
import secrets
def generate_random_number():
random_number = secrets.randbits(32) # Generate a 32-bit random number
return random_number
print(generate_random_number()) # Output a random number between 0 and 4294967295
```

## Conclusion

Random numbers in computers are mathematical formulas and predictable. Not every random number generator is suitable for cryptography and security usage. Random numbers are just one element in security system design and implementation. There are many other things like seed generation, key management, and overall security system design that are extremely important and hard to get right. The Crypto 101 is a great place to start learning more about cryptography.