java.security.SecureRandom is a more secure version of java.util.Random which provides a Cryptographically Secure Pseudo-Random Number Generator (CSPRNG).
java.security.SecureRandom is always preferred over
java.util.Random for generating sensitive random numbers, such as generating an encryption key in a cryptographic application or session ID on a web server or in password generators to create highly secure passwords.
Here are few reasons why
java.security.SecureRandom should be used in sensitive applications –
java.util.Random implementations uses a Linear Congruential Generator (LCG) to produce pseudo-random values which are highly predictable.
On the other hand, most
java.security.SecureRandom implementations uses a pseudo-random number generator (PRNG), which use a deterministic algorithm to produce a pseudo-random sequence from a true random seed.
java.util.Random uses the system time for the seed.
java.security.SecureRandom takes random data from underlying operating system. In case of Linux/Solaris, the random numbers are created from entropy pool by reading from
3. If two instances of
java.util.Random are created with the same seed, and the same sequence of method calls is made for each, they will generate and return identical sequences of numbers. This is not the case with
java.security.SecureRandom, which seeds itself from sources of entropy obtained from the operating system, such as timings of I/O events, which are practically undetectable.
java.util.Random class uses a 48-bit seed, whereas
java.security.SecureRandom usually uses a 128-bit or 160-bit seed. Therefore, only 248 attempts are required to break Random class, which might not even take a second on modern computers. On the other hand, 2128 or 2160 attempts will be required for SecureRandom, which would take years to break even with today’s CPUs computational power.
java.security.SecureRandom produces non-deterministic output as it doesn’t depend upon system clock for seed value. So it is impossible to predict previous and future random numbers.
java.util.Random, on the other hand, uses the system clock as the seed and can be easily reproduced if the time at which the seed was generated is known.
6. LCGs are very fast and typically require only 32- or 64-bits to retain state. On the other hand, creating a
java.security.SecureRandom instance is quite expensive than creating a
java.util.Random instance and is about 30-50 times slower than Random.
nextBytes() methods of SecureRandom may get blocked on Linux if not enough entropy is available and as entropy is being gathered in
/dev/random file. Here’s what wikipedia has to say:
The generator keeps an estimate of the number of bits of noise in the entropy pool. From this entropy pool random numbers are created. When read, the
/dev/random device will only return random bytes within the estimated number of bits of noise in the entropy pool.
/dev/random should be suitable for uses that need very high quality randomness such as one-time pad or key generation. When the entropy pool is empty, reads from
/dev/random will block until additional environmental noise is gathered.
7. It is worth noting that
java.security.SecureRandom is a subclass of
java.util.Random and inherits all
nextX() methods from it where X can be Boolean, Double, Float, Gaussian, Int and Long.
8. Initialization of
Random can be initialized as :
Random rand = new Random(System.nanoTime());
SecureRandom can be initialized as:
SecureRandom rand = new SecureRandom(SecureRandom.getSeed(20));
Here, the number 20 denotes 160-bit seed as 20 bytes = 160 bits.
9. Javadoc itself suggests to use
java.security.SecureRandom to get a cryptographically secure pseudo-random number generator in security-sensitive applications.
Thanks for reading.