开发者

OS-independent random byte sequence in PHP

I would like to generate a random byte sequence to be used in a security-sensitive context. I am looking for an OS-independent way, so I cannot access /dev/(u)random. Furthermore, openssl_random_pseudo_bytes() might not be available so let's forget about it too. I am also not interested in开发者_C百科 performance differences in any of the cases.

Looking at the phpass library (which is used by many and considered to be secure enough) to generate random sequences it falls back to to following algorithm if /dev/urandom is not available:

// Init:
$this->random_state = microtime();
if (function_exists('getmypid'))
    $this->random_state .= getmypid();

// Generate
$count = ...number of bytes to generate
$output = '';
for ($i = 0; $i < $count; $i += 16) {
    $this->random_state =
        md5(microtime() . $this->random_state);
    $output .=
        pack('H*', md5($this->random_state));
}
$output = substr($output, 0, $count);
// $output ready

The above algorithm basically relies on getmypid(), md5() and microtime() to generate random sequences. It has been pointed out by many that time/microtime and pid are a bad source of entropy for secure applications, and so even if you transform these with md5 and some string operations, the output won't be 'securely random' either. So we know that the above algorithm is at best only as good as pid and microtime are as entropy sources.

In contrast here is another algorithm. Given that rand is seeded automatically by PHP, it is (probably) not better than the previous algorithm security-wise since rand/mt_rand are also seeded with computer time and pid by default (ref). But since it is much less complex, wouldn't it be a better alternative? I can also rephrase the question: given that both the algorithm above and that below rely on pid and computer time to generate random numbers, should the above still be superior and why?

function RandomBytes($len)
{
    // Seed
    $seed = (double)microtime()*1000003;
    if (function_exists('getmypid'))
            $seed += getmypid();
    mt_srand($seed);

    $output = '';
    for ($i = 0; $i < $len; ++$i)
        $output .= chr(mt_rand(0, 255));

    // optionally transform using pack('H*', ...) to make output printable
    return $output;
}

And as a last question, do you know a better (=more random) way than any of the above to generate random bytes in an OS-independent manner in PHP?


Be careful to rely on OS implemented pseudo-random generator, if strongly correctness is required. Specially for security and simulations. Pseudo random generators are not difficult to be implemented, have a look here for a bit of theory and some references.


You could attempt to use OS resources if they exist, and then fall back to something homegrown when these resources do not exist and you have no other choice. See this answer on another forum for an example.

On Windows systems that support .NET you can use the DOTNET php class together with the System.Security.Cryptography.RNGCryptoServiceProvider class.


The best random number generator you can possibly use is /dev/random. If this interface is not accessible then you maybe on a windows system in that case you can use the much less secure System.Security.Cryptography.RNGCryptoServiceProvider. The function mt_rand() should be a distant 3rd place in terms of how random its output is.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜