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):
The 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 setSeed
methods.
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 nextBytes
.
- 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 setseed
:
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.