Java tutorials home  java.util.Random  Random number generators  XORShift  High quality random  Seeding generators  Entropy  SecureRandom  Random sampling  Random simulations and nextGaussian()

The Java SecureRandom class

The SecureRandom class, housed in the java.security package, provides a drop-in replacement to java.lang.Random. But unlike the latter, java.security.SecureRandom is designed to be cryptographically secure. We'll look in more detail below at what this means. First, let's address the question from a simple, practical point of view: when should you use SecureRandom?

When to use SecureRandom

SecureRandom is typically used in cases where:

  • random numbers are generated for security related purposes, such as generating an encryption key or session ID (see below);
  • or, more generally, high-quality randomness is important and it is worth consuming CPU (or where CPU consumption isn't an issue) to generate those high-quality random numbers.

On the other hand, it may not be an appropriate generator where CPU time need to generate numbers is a factor that is worth trading for quality of randomness. As a rough guide:

SecureRandom is about twenty to thirty times slower than "good medium-quality" generators such as the XORShift or the Numerical Recipes combined generator.

CPU usage may be an issue, for example, in:

  • a simulation or Monte Carlo experiment where a very large quantity of numbers needs to be generated quickly;
  • where a moderate quantity of numbers needs to be generated but where there are "better things to spend the CPU time on" (e.g. a non-gambling game where the quality of randomness isn't crucial);
  • a multi-user environment where a moderate quantity of numbers needs to be generated but with minimal impact on other processes.

Properties of SecureRandom

We said that SecureRandom is designed to be cryptographically secure. In practice, this means that the generator has the following properties:

  • given only a number produced by the generator, it is (to all intents and purposes) impossible to predict previous and future numbers;
  • the numbers produced contain no known biases;
  • the generator has a large period (in Sun's standard implementation, based on the 160-bit SHA1 hash function, the period is 2160);
  • the generator can seed itself at any position within that period with equal probability (or at least, it comes so close to this goal, that we have no practical way of telling otherwise).

These properties are important in various security applications. The first is important, for eaxmple, if we use the generator to produce, say, a session ID on a web server: we don't want user n to predict user n+1's session ID. Similarly, we don't want a user in an Internet cafe, based on the session ID or encryption key that they are given to access a web site, to be able to predict the value assigned to a previous user on that machine.

The other properties are together important when picking, say, a session ID or encryption key, to ensure that any of all the possibly values (or a sufficient proportion of them) can be selected, and we'll take a moment now to consider why.

The importance of producing "all values with equal probability"

For example, let's say that we want to pick a 128-bit AES encryption key. The idea of a strong encryption algorithm such as AES is that in order for an adversary to guess the key by "brute force" (which we assume is the only possible means), they would have to try every single possible key in turn until they hit on the right one. By law of averages, we would expect them to find it after half as many guesses as there are possible keys. A 128-bit key has 2128 possible values, so on average, they would have to try 2127 keys. In decimal 2127 is a 39-digit number. Or put another way, trying a million million keys per second, it would take 5x1015 millennia to try 2127 keys. Not even the British government wants to decrypt your party invitations that badly. So with current mainstream technology1, a 128-bit key is in principle sufficient for most applications.

But these metrics hold true only if our key selection algorithm— i.e. our random number generator— genuinely can pick any of the possible keys. For example, we certainly should not choose the key as follows:

// This is WRONG!! Do not do this!
Random ranGen = new Random();
byte[] aesKey = new byte[16]; // 16 bytes = 128 bits
ranGen.nextBytes(aesKey);

The problem here is that the period of java.util.Random is only 248. Even though we're generating a 128-bit key, we will only ever pick from a subset of 248 of the possible keys. Or put another way: an attacker need only try on average 247 keys, and will find our key by trial and error in a couple of days if they try just a thousand million keys per second. And as if that wasn't bad enough, they probably don't even need to try anywhere near 247: for reasons discussed earlier, there's a good chance that an instance of java.util.Random created within a couple of minutes of bootup will actually be seeded from a about one thousandth of the 248 possible values. This time, HM Sniffing Service doesn't even need expensive hardware to find the secret location of your housewarming party: a trip to Staples will give them all the computing power they need.

So as you've probably guessed, our solution to the problem is to use SecureRandom instead:

import java.security.SecureRandom;
..
Random ranGen = new SecureRandom();
byte[] aesKey = new byte[16]; // 16 bytes = 128 bits
ranGen.nextBytes(aesKey);

Now, there's a good chance that any of the 2128 possible keys will be chosen.

Seeding of SecureRandom

In order to provide this property of choosing any seed with "equal" likelihood, (or at least, with no bias that is practically detectable), SecureRandom seeds itself from sources of entropy available from the local machine, such as timings of I/O events.


1. Note that with a quantum computer, the complexity of guessing the key is apparently proportional to the square root of the number of possible keys. Then, guessing the 128-bit key at the same rate would take only about 200 days.

comments powered by Disqus

Written by Neil Coffey. Copyright © Javamex UK 2013. All rights reserved.