CAUTION: The seeding planned in the question has the potential to remove the default best-effort seeding normally provided by
SecureRandom. It will actually do so with some security Providers. Some others will produce true random no matter what.
Worse, the seeding planned might make the output predictable by spying the machine's communication with random.org.
The specification of SecureRandom in Java (1.)5 and down to at least (1.)3 states (emphasis added):
SecureRandom implementation attempts to completely randomize the internal state of the generator itself unless the caller follows the call to a getInstance method with a call to one of the
Java 8 is even clearer:
If setSeed is not called, the first call to
nextBytes will force the
SecureRandom object to seed itself. This self-seeding will not occur if
setSeed was previously called.
Recommendable practical ways to generate random numbers which are indistinguishable from true random assuming everything works as specified are:
- Right after the
SecureRandom constructor, perform a single
nextBytes with some small
numBytes >0 and disregard the result (even though 0 should do if a Vulcan implemented the spec), then
setseed with whatever unpredictable data at hand, then use
- Do not
setseed, directly use
nextBytes; but that additionally assumes that the runtime is able to supply entropy.
Method 1 is guaranteed not to lose the default best-effort seed, for in
The given seed supplements, rather than replaces, the existing seed.
The above statement is leaving out an implicit and much needed: if any ! Notice that the additional statement:
Thus, repeated calls are guaranteed never to reduce randomness.
only guarantees that the second and later
setseed can't reduce randomness.
This quirk of the Java crypto API is a feature intended for testing: an initial
setseed can make tests reproducible. That can be useful. Unfortunately it works, or not, depending on security Providers (at least, and to my knowledge only), and I know no way to tell other than trying. More generally the Java crypto API is complex and occasionally error-prone, to the point that it is hard to be sure that you will reliably get what you want to get, even though casual testing might suggest so.