I helped a colleague recently determine whether Java Random() was worth using in a situation where the client had to be certain that the numbers were truly random.
Our concern was that while a small sample of random numbers (especially while seeded with the current time ) are fit for most purposes they are not appropriate where due dillegence needs to be performed.
The reason being most random number generators are only pseudo random.
So we did some research and asked some of our experts about the suitability
of the Java Random function. Things to note are defined below:
- Most of the documents on the subject are quite old and therefore there may be improvements, but I couldn’t find anything which said it had materially changed.
- It is worth noting that we are looking at Pseudo Random Number Generators and not truly random numbers. For the use cases discussed I don’t believe that would be an issue, but that would not be the case in some gambling and cryptography applications
- Where true random numbers are required, a random number service and/or specific random number hardware is used. I don’t believe this is required in this application [https://api.random.org/json-rpc/1/]
- People have been fairly scathing of Java Random, identifying that the current implementation only uses 17 bits of entropy from the initial seed (i.e. 1 in 131072 starting points) and demonstrates repeating patterns after low numbers of calls to generate numbers (of the order of ~50000). Statistical tests have been used to identify that it doesn’t produce very good random numbers [http://www.alife.co.uk/nonrandom/]
- SecureRandom is a drop in replacement for Random and does produce much better random numbers that pass Statistical tests, but it is 60 times slower than Random [https://dzone.com/articles/java-programmer%E2%80%99s-guide-random]. In the way that the Batch report is using random numbers, it appears that of the order of 500 random numbers would be required. A quick test shows that 500 SecureRandom numbers only takes ~15 Milliseconds to calculate. Which isn’t going to significantly affect the time taken for a result.
- There are libraries that support alternative ways of creating random numbers. These produce good quality pseudo random numbers in less time than the standard Java implementations, but would require additional libraries and dependencies to be managed. In this case I do not believe it would be worth the additional effort. [http://maths.uncommons.org/] [https://www.bouncycastle.org/java.html]
Based on the
number of random numbers being generated (maximum of around 500 at a time),
Random may well be sufficient. But given the minimal cost of using
SecureRandom it may be worth converting to that instead, to remove even a small
possibility of concern.