Difference Between Java.Util.Random and Java.Security.Securerandom

Difference between java.util.Random and java.security.SecureRandom

The standard Oracle JDK 7 implementation uses what's called a Linear Congruential Generator to produce random values in java.util.Random.

Taken from java.util.Random source code (JDK 7u2), from a comment on the method protected int next(int bits), which is the one that generates the random values:

This is a linear congruential pseudorandom number generator, as
defined by D. H. Lehmer and described by Donald E. Knuth in
The Art of Computer Programming, Volume 3:
Seminumerical Algorithms, section 3.2.1.

Predictability of Linear Congruential Generators

Hugo Krawczyk wrote a pretty good paper about how these LCGs can be predicted ("How to predict congruential generators"). If you're lucky and interested, you may still find a free, downloadable version of it on the web. And there's plenty more research that clearly shows that you should never use an LCG for security-critical purposes. This also means that your random numbers are predictable right now, something you don't want for session IDs and the like.

How to break a Linear Congruential Generator

The assumption that an attacker would have to wait for the LCG to repeat after a full cycle is wrong. Even with an optimal cycle (the modulus m in its recurrence relation) it is very easy to predict future values in much less time than a full cycle. After all, it's just a bunch of modular equations that need to be solved, which becomes easy as soon as you have observed enough output values of the LCG.

The security doesn't improve with a "better" seed. It simply doesn't matter if you seed with a random value generated by SecureRandom or even produce the value by rolling a die several times.

An attacker will simply compute the seed from the output values observed. This takes significantly less time than 2^48 in the case of java.util.Random. Disbelievers may try out this experiment, where it is shown that you can predict future Random outputs observing only two(!) output values in time roughly 2^16. It takes not even a second on a modern computer to predict the output of your random numbers right now.

Conclusion

Replace your current code. Use SecureRandom exclusively. Then at least you will have a little guarantee that the result will be hard to predict. If you want the properties of a cryptographically secure PRNG (in your case, that's what you want), then you have to go with SecureRandom only. Being clever about changing the way it was supposed to be used will almost always result in something less secure...

Is SecureRandom.ints() secure?

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.

Is java.secure.random a sufficient choice for gambling industry?

As others say, the secure RNG can have limited throughput. To mitigate this
you can either stretch that secure randomness by seeding a CPRNG, or you can
try to optimise your usage of the bitstream.

To shuffle a pack of cards, for example, you need only 226 bits, but a naive
algorithm (calling nextInt(n) for each card) will likely use 1600 or 3200
bits, wasting 85% of your entropy and making you seven times more susceptible
to delays.

For this situation I think the Doctor Jacques
method would be appropriate.

To go with that, here's some performance analysis against progressively more
costly entropy sources (also contains code):

Bit recycling for scaling random number generators

I would lean towards efficient usage rather than stretching, because I think it
would be a lot easier to prove the fairness of an efficient consumer of a
trustworthy entropy stream, than to prove the fairness of any drawing method
with a well-seeded PRNG.


EDIT2:
I don't really know Java, but I put this together:

public class MySecureRandom extends java.security.SecureRandom {
private long m = 1;
private long r = 0;

@Override
public final int nextInt(int n) {
while (true) {
if (m < 0x80000000L) {
m <<= 32;
r <<= 32;
r += (long)next(32) - Integer.MIN_VALUE;
}
long q = m / n;
if (r < n * q) {
int x = (int)(r % n);
m = q;
r /= n;
return x;
}
m -= n * q;
r -= n * q;
}
}
}

This does away with the greedy default uniform [0,n-1] generator and replaces it with a modified Doctor Jacques version. Timing a card-shuffle range of values shows almost a 6x speed-up over the SecureRandom.nextInt(n).

My previous version of this code (only 2x speed-up) assumed that SecureRandom.next(b) was efficient, but it turns out that call was discarding entropy and dragging the whole loop down. This version manages its own chunking.

Generate secure random number uniformly over a range in Java

You can do

Random rand = new SecureRandom()
// 0 to 100 inclusive.
int number = rand.nextInt(101);

or

// 0 inclusive to 100 exclusive.
int number = rand.nextInt(100);

Note: this is more efficient than say (int) (rand.nexDouble() * 100) as nextDouble() needs to create at least 53-bits of randomness whereas nextInt(100) creates less than 7 bits.

Java SecureRandom declaration should be static class specific or can be instance specific

No, don't make it static. If you want you can make it an instance field, but making it a class field is not optimal. E.g. see the note on thread-safety on the Random class that it has been derived from:

Instances of java.util.Random are threadsafe. However, the concurrent use of the same java.util.Random instance across threads may encounter contention and consequent poor performance. Consider instead using ThreadLocalRandom in multithreaded designs.

Beware though that the ThreadLocalRandom is not cryptographically secure, and therefore not a good option for you. In general, you should try and avoid using static class fields, especially when the instances are stateful.

If you only require the random instance in one or a few methods that are not in a tight loop then making it a local instance is perfectly fine (just using var rng = new SecureRandom() in other words, or even just new SecureRandom() if you have a single method call that requires it).

Seed to java.security.SecureRandom on Windows os

The class java.security.SecureRandom Uses the system API provided by the OS host. Each OS has their own process to generate random numbers.

In Windows SecureRandom uses the method CryptGenRandom that is part of WinCrypt Windows library (Included in Advapi32.dll of Windows System libraries).

All the documentation about the Windows function is available in the Microsoft docs of CryptGenRandom

Should SecureRandom be used as singleton or a new object should be created each time random number is generated?

Should SecureRandom be used as singleton or a new object should be created each time random number is generated?

You should not create many SecureRandom instances. It is expensive, and liable to drain your system's source of entropy (randomness).

If you run out of entropy, the SecureRandom creation is liable to block in a syscall ... waiting ... for ... more entropy to be harvested.

Does it make any difference with respect to predictability.

It should not make any difference to predictability. If you treat a seeded SecureRandom as a black box, it should not be possible to predict the next number unless you know the seed and the previous history of the generator.

The caveat is that a flawed implementation of a secure random number generator may not actually be secure. (But the flipside is that the entropy you are using to generate seeds may not be as random as you think ... either.)

This question arose after reading about ... 'Predictability of Linear Congruential Generators'.

LCGs are fundamentally not secure. You could not use one for a SecureRandom implementation.

The javadoc includes references to the requirements for any SecureRandom implementation. If you have practical concerns, read the references.

Should I prefer ThreadLocalRandom or SecureRandom?

As described in its javadoc, ThreadLocalRandom is similar to Random (i.e. not secure) but with better performance in case of concurrent access.

Instances of ThreadLocalRandom are not cryptographically secure. Consider instead using SecureRandom in security-sensitive applications.



Related Topics



Leave a reply



Submit