Is SecureRandom.ints() secure?

JavaSecurityRandom

Java Problem Overview


It is known that SecureRandom class provide strong cryptographic security for generated random number. java.util.Random is insecure for the situation which requires cryptographic security. The typical usage of SecureRandom is:

SecureRandom random = new SecureRandom();
byte bytes[] = new byte[20];
random.nextBytes(bytes);

However, I met a case:

SecureRandom random = new SecureRandom();
int number = random.ints();

The method ints() is inherited from the java.util.Random class. I am confused when SecureRandom which is a secure random number generator uses a method inherited from the insecure random number generator, whether it is secure?

Java Solutions


Solution 1 - Java

Yes it is secure.

Code examination of java.util.Random shows that ints() creates a spliterator that uses internalNextInt(...) to generate the random integers. That in turn calls nextInt() on this. In the case of java.security.SecureRandom, nextInt() is overridden to generate a "secure" random number1.

You can confirm this for yourself by looking at the source code.


1 - Of course, it doesn't actually make sense to call an integer or a sequence of integers "secure". And there are situations where SecureRandom may not have the properties that you require. (It depends on the actual RNG or PRNG implementation used by the class, the quality of the supplied seed or system provided entropy source, and so on.) But SecureRandom::ints() will generate a sequence of integers that has the same properties as if you made a sequence of SecureRandom::nextInt() calls on the same object. If the latter sequence is suitable for your purposes (whatever they are) then so is the former.

Solution 2 - Java

Random.ints() is a method that returns an IntStream. An IntStream is neither secure nor insecure: it's a stream of numbers.

The "security" of the sequence of ints returned by the method depends on the implementation of the method. SecureRandom generates its "random" values more securely than Random. They share the same API, and thus you can use either in a given context depending upon your requirements.

So, the fact it inherits from an insecure class is irrelevant to the security: you can reasonably trust that the SecureRandom class is as secure as the documentation says it is.


Consider an analogy with HashSet: this makes no guarantees of the iterator ordering; however, LinkedHashSet, a subclass of HashSet does guarantee iterator ordering. The guarantee of LinkedHashSet is consistent with the guarantee of HashSet, because a specific ordering is one of the possible orderings that could be observed with "no guaranteed ordering" (after all, you have to return the elements in some order).

Similarly, Random makes no guarantees about the security of the sequence of ints returned; SecureRandom makes stronger guarantees. But there is no reason why the sequence of ints from a SecureRandom couldn't also be returned by a Random, by coincidence.

Solution 3 - Java

Yes, SecureRandom

> provides a cryptographically strong random number generator (RNG).

One important factor for a secure RNG is the seed.

> Therefore any seed material passed to a SecureRandom object must be unpredictable, and all SecureRandom output sequences must be cryptographically strong, as described in RFC 4086: Randomness Requirements for Security.

Go ahead and use it. If you are interested in the details, read the JavaDoc which describes the various approaches used by implementations.

Solution 4 - Java

ints method

Yes, it is secure, as long as nextInt() is secure (for the number of integers retrieved from the stream).

According to the documentation of the Random#ints() method:

> A pseudorandom int value is generated as if it's the result of calling the method nextInt().

Now in turn, Random#nextInt:

> The method nextInt is implemented by class Random as if by (returning) next(32)

next(int) is a protected method that you cannot call, but which can be overridden in implementing classes.

Which in turn is implemented as SecureRandom.next(32) if you use an instance of SecureRandom rather than Random:

> Generates an integer containing the user-specified number of pseudo-random bits (right justified, with leading zeros). This method overrides a java.util.Random method, and serves to provide a source of random bits to all of the methods inherited from that class (for example, nextInt, nextLong, and nextFloat).

So in the end a method of SecureRandom is called, and if that's secure then the stream of random numbers is secure. Now to be honest, that statement is wrong in the sense that it isn't used for nextBytes, but it is certainly used for any method that returns number values.

SecureRandom implementation

If you're already sure that the SecureRandom that you use is secure, then you can stop reading here.

Now you'd think that it would end here, but SecureRandom by itself does not implement a random bit generator. Instead, it simply depends on a particular service class within the configured provider which implements SecureRandomSpi (Spi means Service Provider Interface, an abstract class a provider has to implement to deliver secure random data to instances of SecureRandom). So in the end an invocation of SecureRandomSpi#nextBytes() will have to be made within SecureRandom#next(int) to retrieve the actual bits.


As stated for Random#next(int) other methods that require numbers or streams of numbers should - in the end - all call this particular method. Now if this is indeed the case depends on the implementation of Random, SecureRandom. If the result is secure depends on the algorithm and the seeding provided by SecureRandomSpi, the actual random bit generator that is used.


I've proven above that the result should be really be cryptographically random, assuming that SecureRandom is cryptographically random. In the end only a full code review for each implementation & version of Java needs to be made to show that it is secure. That's outside of scope for StackOverflow though, you may need support from e.g. Oracle, IBM or Google to retrieve test documents and reviews, or you may perform such a review yourself for a particular implementation, of course. Most of it - if not all of it - is Open Source after all.

Solution 5 - Java

Yes,

the previous solutions are using pseudo-random numbers. SecureRandom is a cryptographically strong random number generator.

The implementation only differs slightly from the ones before. Frankly speaking, it is a drop-in replacement for Random:

public static void main(String[] args) {
    SecureRandom current = new SecureRandom();
    // [0, 101)
    System.out.println(current.nextInt(101));
    System.out.println(current.nextInt(101));
}

For more see Java Random Number Generation.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionYa XiaoView Question on Stackoverflow
Solution 1 - JavaStephen CView Answer on Stackoverflow
Solution 2 - JavaAndy TurnerView Answer on Stackoverflow
Solution 3 - Javauser11044402View Answer on Stackoverflow
Solution 4 - JavaMaarten BodewesView Answer on Stackoverflow
Solution 5 - JavaJeffView Answer on Stackoverflow