Use secure random number generators, please


Disclaimer

The current article is an introductory article about the practical usage of different generators in standard libraries of other languages. It is the reason we do not explore different pseudo-random algorithms.

The article tries to help avoid the most common issues of developers.

If you have to use a specific random algorithm, certified algorithms, or algorithm forced by your security team or developer’s collegium (for example, some security products and products with specific regulations), just use it.

Motivation

I have seen few real-world security issues related to the topic in projects I worked on them.

Some news (I remember only one the newest of them, I heard about):

Knowing the creation date of an account, an attacker can try to bruteforce the account password with a small range of passwords (~100) and gain access to it.

— donjon.ledger.com1

What random is

On the one hand, random is a simple entity to understand. Random value - is a value that someone cannot predict.

On the another hand, computer science did not find a solution for the problem with the name “random”. All values generated by pseudo-random algorithms we name as “random”. All randomization algorithms have name pseudo-random because they do not generate really random values.

True random number generators

“true random” is more or less a natural random number generator. Specific devices can generate these values. These devices use several techniques for generating entropy, such as atmospheric noise, reverse bias semiconductors and beam splitting (for example - Recommendation for the Entropy Sources Used for Random Bit Generation).

There is at least one service with APIs that can be used to generate “true random” values:

Pseudo-random number generators

In all languages I’ve seed before presented at least two different types of random number generators:

Pseudo-random number generator (PRNG)

PRNG is a predictable number generator with the ability to specify custom “seed”.

Seed is a value that uses as a starting value for the following random values mathematically calculated from previously generated values.

It means that everyone who knows used seed can generate the same infinite sequence of numbers.

When to use:

  • We need to have predictable random values, and we save seeds between generated values
  • We write a performance-sensitive application, and we do not use random functions for sensitive data

When not to use:

  • Use this function NEVER, until you are sure you HAVE TO use it in your particular case

Small suggestion

If you decided to use this random and you want or need to specify your custom seed. Use, please, something less predictable than the then-current timestamp in seconds.

Possible ideas (higher is better in my opinion):

  1. If you can use some secure random algorithm use decided to use a faster solution, then generate seed once by secure random and use the selected algorithm after that
  2. If you cannot use secure random at all, use different unique values from your node, like the PID of an app, timestamp in nanoseconds, IP address, mac address, etc. Combine as many unique values as you can
  3. Use, at least, UNIX timestamp in nanoseconds with PID

Cryptographically secure random number generator (CSPRNG)

CSPRNG is also a pseudo-random number generator and also mathematical, but it uses more complicated rules and algorithms to make it challenging to predict random values.

These algorithms are usually suggested to use for “real” sensitive generated values. I’m not a security expert to contradict this statement, but I have a reason to add more rules for using secure random.

Usually, software engineers are not so familiar with security (I’m as well) as we think we are. So when developers write some feature, they think the particular random number will not affect safety, but it can affect it in the future.

When not to use:

  • Use a basic CSPRNG provided by a programming language whenever you need random bytes, and you did not decide to use the faster one.
  • Investigate more secure implementation in a language or external libraries, if you need a certified crypto-secure generator

When not to use:

From my perspective, there are only two reasons to stop using this solution:

  • Performance issues that require to switch to something faster
  • Platform limitations where no way to use this kind of generators

Summary

Until developers are sure what they are doing (even better to get approval from the security team for a particular use case), I’d suggest using CSPRNG from a language.

In libraries, a good way would be to provide options between different random functions and specify crypto-random generators by default.


  1. First found website, because I remember the issue from news ↩︎

  2. In some languages this type of random named as mathematical, for example Golang math/rand, JavaScript and Java Math.random ↩︎