Gathering entropy in web apps to create (more) secure random numbers Gathering entropy in web apps to create (more) secure random numbers php php

Gathering entropy in web apps to create (more) secure random numbers


In the best scenario, your biggest danger is a local user disclosure of information exploit. In the worst scenario, the whole world can predict your data. Any user that has access to the same resources you do: the same log files, the same network devices, the same border gateway, or the same line that runs between you and your remote connections allows them to sniff your traffic by unwinding your random number generator.

How would they do it? Why, basic application of information theory and a bit of knowledge of cryptography, of course!

You don't have a wrong idea, though! Seeding your PRNG with real sources of randomness is generally quite useful to prevent the above attacks from happening. For example, this same level of attack can be exploited by someone that understands how /dev/random gets populated on a per-system basis if the system has low entropy or its sources of randomness are reproducible.

If you can sufficiently secure the processes that seed your pool of entropy (for example, by gathering data from multiple sources over secure lines), the likelihood that someone is able to listen in becomes smaller and smaller as you get closer and closer to the desirable cryptographic qualities of a one-time pad.

In other words, don't do this in PHP, using a single source of randomness fed into a single Mersenne twister. Do it properly, by reading from your best, system-specific alternative to /dev/random, seeding its entropy pool from as many secure, distinct sources of "true" randomness as possible. I understand you've stated that these sources of randomness are inaccessible, but this notion is strange when similar functions are afforded to all major operating systems. So, I suppose I find the concept of an "auxiliary system" in this context to be dubious.

This will still be vulnerable to an attack by a local user cognizant of your sources of entropy, but securing the machine and increasing the true entropy within /dev/random will make it far more difficult for them to do their dirty work short of a man-in-the-middle attack.

As for cases where /dev/random is indeed accessible, you can seed it fairly easily:

  • Look at what options exist on your system for using /dev/hw_random
  • Embrace rngd (or a good alternative) for defining your sources of randomness
  • Use rng-tools for inspecting and improving your randomness profile
  • And finally, if you need a good, strong source of randomness, consider investing in more specialized hardware.

Best of luck in securing your application.


PS: You may want to give questions like this a spin at Security.SE and Cryptography.SE in the future!


Use Random.Org

If you need truly random numbers, use random.org. These numbers are generated via atmospheric noise. Besides library for PHP, it also has a http interface which allows you to get truly random numbers by simple requests:

https://www.random.org/integers/?num=10&min=1&max=6&col=1&base=10&format=plain&rnd=new

This means that you can simply retrieve the real random numbers in PHP without any additional PECL exension on the server.

If you don't like other users to be able to "steal" your random numbers (as MrGomez' argues), just use https with a certificate checking. Here follows an example with https certificate checking:

$url = "https://www.random.org/integers/?num=10&min=1&max=6&col=1&base=10&format=plain&rnd=new";$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);$response = curl_exec($ch);if ($response === FALSE)        echo "http request failed: " . curl_error($ch);else        echo $response;    curl_close($ch);

If you need more information on how to create https requests:

More on security

Again, some might argue that if the attacker queries random.org at the same time as you, he might get the same numbers and predict.. I don't know if random.org would even work this way, but if you are really concerned, you may lessen the chance by fooling the attacker with dummy request which you throw out, or use only a certain part of the random numbers you get.

As MrGomez notes in his comment, this shall not be considered as an ultimate solution to security, but only as one of possible sources of entropy.

Performance

Of course, if you need a blitz latency then doing one random.org request per one client request might not be best idea... but what about just doing one bigger request to pre-cache the random numbers like every 5 minutes?


To come to the point, as far as i know there is no way to generate entrophy inside a PHP script, sorry for this non-answer. Even if you look at well etablished scripts like phppass, you will see, that their fallback system cannot do some magic.

The question is, whether you should try it anyway or not. Since you want to publish your system under GPL, you propably don't know in what scenario it will be used. In my opinion it's best then to require a random source, or to fail fast (die with an appropriate error message), so a developer who wants to use your system, knows immediately, that there is a problem.

To read from the random source, you could call the mcrypt_create_iv() function...

$randomBinaryString = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);

...this function reads from the random pool of the operating system. Since PHP 5.3 it does it on Windows servers as well, so you can leave it to PHP to handle the random source.