If you need a random number you are usually advised to use SecureRandom because it gives a cryptographically secure random number.
Typical way of calling SecureRandom would be:
1 2 3 |
SecureRandom secureRandom = new SecureRandom(); byte bytes[] = new byte[16]; secureRandom.nextBytes(bytes); |
From a random generator seeding perspective this is also the correct way. You might be tempted to call the setSeed in order to seed with some long that you provide. Resist that temptation unless you can prove that the seed obeys the constraints of your application (like that it is different between different instantiations and invocations of SecureRandom). And no, seeding with the System.currentTimeMillis() will not work: multiple threads can get the same value.
Here’s an excerpt from the setSeed documentation:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/** * Reseeds this random object, using the eight bytes contained * in the given {@code long seed}. <strong>The given seed supplements</strong>, * rather than replaces, the existing seed. Thus, repeated calls * are guaranteed never to reduce randomness. * * <p>This method is defined for compatibility with * {@code java.util.Random}. * * @param seed the seed. * * @see #getSeed */ |
The interesting part here is that it says that the seed “supplements” the internal seed. This is not what I found. The given seed will completely replace the internal seed. This means that when seeded the same way two SecureRandom will return the same value. Probably not what you would expect.
1 2 3 4 5 6 7 8 9 10 11 |
SecureRandom secureRandom1 = new SecureRandom(); secureRandom1.setSeed(1L); byte[] bytes1 = new byte[16]; secureRandom1.nextBytes(bytes1); SecureRandom secureRandom2 = new SecureRandom(); secureRandom2.setSeed(1L); // Same seed here. byte[] bytes2 = new byte[16]; secureRandom2.nextBytes(bytes2); assertTrue(Arrays.equals(bytes1, bytes2)); // This assertion is correct. |