# Practical way to generate random numbers from PRNG which are indistinguishable from true random

I am working on a project where I want the user to be able to create random data. For that I use a cryptographically random generator (Java's SecureRandom, which uses OS entropy source if available). Additionally I will seed this PRNG with a true 16 byte (or is more needed?) random number (from e.g. random.org). One seed usually only creates less than 1 MB of random data.

Is that a sound approach to generate random data that is indistinguishable from true random data?

Are there any steps to take to strengthen the security? Eg. scramble the seed to make it harder for an attacker who is listening to know what seed was used?

• If you really want to incorporate 16 byte seed, there are two ways to go 1. each time you need new data from prng, You can get 16byte of random data from somewhere else and seed it to prng which generates the required random data for you. You can use AES in CTR mode to act as a PRNG and 16 Byte seed as key. Then total security will be dependent upon keeping the 16 bytes secure. 2. Use Fortuna, collect entropy from various sources and generates random numbers Aug 31 '17 at 10:15
• @1 is block cipher in CTr mode better than e.g. Java's SecureRandom? @2 SecureRandom uses the OS entropy sources (e.g. Dev/random), seeding it should only make the internal seed better by xor ing, so it would be a mixture from external and internal randoms. Aug 31 '17 at 10:28
• Since at least Java 6 it states: "Reseeds this random object. The given seed supplements, rather than replaces, the existing seed. Thus, repeated calls are guaranteed never to reduce randomness." docs.oracle.com/javase/6/docs/api/java/security/… Aug 31 '17 at 11:50
• For cryptographically secure randomness, do not rely on 3rd parties like random.org as there is no need to (and it may even introduce attack vectors which you'll want to avoid). Every modern computer system is very well capable of providing cryptographically secure randomness, and every modern OS has an according system call to fetch that randomness from its randomness pool — which is what that Java function does behind the screens… use the OS secure randomness function. Aug 31 '17 at 12:39
• how much entropy does the java secure random provides? can we trust it to provide 128 or 256 bit of security? if yes then i stand corrected and please use already available secure random. Aug 31 '17 at 19:01

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:

1. 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.
2. 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.

SecureRandom is designed to be just that, and it achieves it quite well without user intervention. It can self seed by the underlying OS's randomness source, via jitter timings of multiple threads it spawns or combinations of the system time and other system specific variabes. In all likelihood though, unless you have a weird platform it will use the OS.

The upshot is that you don't need to manually seed the generator. Just call it as SecureRandom(). Since the actual output is a simple SHA1 iterative counter algorithm, you have the security of SHA1 itself. The recent SHAttered attacks on it do not effect the quality or predictability of it's use a PRNG. I'm unaware of any work to distinguish SecureRandom's output from random.

A warning. There are two issues with your idea of acquiring an external seed from Random.org. Firstly, it can be recorded by anyone sniffing the network. Secondly, there is no evidence that Random.org is a source of true randomness. There is no detail on their site and the implementation is closed source. It is very difficult to pick up atmospheric noise with a consumer radio. Radios pick up Lady Gaga. And police radios and mobile phones. Simply have a look at the constituents of the EM spectrum (8400 × 5375 pixel image ). Tuned between stations is essentially rubbish. If you look at levels, atmospheric noise is only ~5% above thermal within the range of an AM receiver. And that's without Clive down the street turning on his misaligned ham set.

If you simply have to get randomness over the internet, use Hotbits instead. They're at least credible.

• The actual output is based on SHA-1 with the default Oracle security Provider, but can be overridden in a number of ways, including configuration of the Oracle runtime. That's not uncommon when there's a HSM or substitute of that around, or in some testing environments.
– fgrieu
Aug 31 '17 at 12:48
• @fgrieu I've seen a lot of servers. Never seen a HSM though. Even online casinos typically use the Twister. Perhaps they're not that common. Aug 31 '17 at 12:59
• @PaulUszak about the warning: how do you figure that Hotbits is more credible than random.org (or say random.irb.hr)? I like them because the have a nice json rpc api with RSA signed randoms and use HTTPS which should make it harder to sniff. As a remedy to sniffying: is there a paradigm on how to make the seed "fuzzy" so an sniffing attacker has a hard time figuring what acutal seed was used? E.g creating new SecureRandom, using externel seed, then calling generateSeed to seed the actual SecureRandom? Aug 31 '17 at 13:07
• Hotbits at least have a proven scientific principle (and debiasing algorithm) involving a radio isotope. All their code is available for inspection. Random's is secret and based on unsound science (see answer). It's probably just a PRNG seeded off thermal noise. And what is atmospheric noise? Radios are specifically designed not to pick this up. The hiss you hear is not atmospheric noise. Aug 31 '17 at 13:20