Prepare for a backend job by mastering computer science fundamentals # Secure Random Numbers in Node JS

By Lane Wagner on Jul 3, 2019

Randomness is a hard problem for computers. Most functions that generate randomness are not considered cryptographically secure. What this means is that it’s possible for attackers to take a good guess at what number a non-secure randomness generator generated. In the case of guessing a randomly generated private key, for example, this can be catastrophic.

## How to generate insecure random numbers

`Math.random()` is a built-in function in JavaScript that returns a floating-point, pseudo-random number in the range 0 to less than 1. By always generating a number between 0 and 1, you can scale the result up to whatever size you need.

### Example - Random number between 0 and 9

``````const betweenOneAndTen = Math.floor(Math.random() * 10)
``````

### Example - Random number between 10 and 100

``````const min = 10
const max = 100
const betweenOneAndTen = Math.floor(Math.random() * (max - min)) + min + 1
``````

## A simple path to your career in backend development The pace of Boot.dev's JavaScript, Python and Go courses has been perfect for me. The diverse community in Discord is a blast, and other members are quick to help out with detailed answers and explanations.

- Daniel Gerep from Cassia, Brasil

## Why is Math.Random insecure?

Many non-secure randomness, or entropy, generators like `Math.Random()` do something similar to the following:

``````function getRandom(timestamp, maxNumber){
// Take the deterministic hash of the timestamp
const hashedTime = sha256(timestamp)
// Reduce the hash to within the range [0, maxNumber)
return hashedTime % maxNumber
}
``````

This function (while ignoring some implementation details of modulus math by such a large number) will return random numbers that are based on the timestamp input, which is called the seed. If I pass in many different timestamps, the various outputs would appear random. This is an example of a weak pseudo-random number generator.

A weak pseudo-random number generator works perfectly fine if one is trying to:

• Create sample data for an application
• Write a video game engine
• etc …

However, weak pseudo-randomness can be catastrophically dangerous if one is trying to:

• Generate Bitcoin keys
• etc …

## Use crypto.randomBytes() for cryptographically secure psuedo-randomness

Node’s built-in crypto.randomBytes() function is a cryptographically secure random number generator that is based on openssl. Depending on the operating system of the user, `randomBytes` will use `/dev/urandom` (Unix) or `CryptoGenRandom (Windows).

While still pseudo-random sources, the important thing is that they are not guessable by an attacker. In other words, after using `crypto.randomBytes()` to generate a secret key for AES-256 encryption, no one will be able to guess the key.

## Should I always use crypto.randomBytes()?

No. There are dangers if you implement your random number generator on top of a low-level API like random bytes. Because it returns bytes and not numbers, it’s up to you to convert the bytes into numbers. If you make a mistake, it can result in a vulnerability in your system.

In short, use crypto.randomBytes() whenever you need raw bytes. If you need a number within a range, for example, a random number between 0-9, then use a non-biased function that uses `crypto.randomBytes()` as the source of entropy. For example: node-random-number-csprng

## Become a backend engineer by building real projects

• Write modern code in JavaScript, Python and Go
• Build and deploy real backend projects to your personal portfolio
• Compete in the job market by mastering computer science fundamentals