PHP中与OS无关的随机字节序列

时间:2011-08-28 15:45:04

标签: php security random

我想生成一个在安全敏感的上下文中使用的随机字节序列。我正在寻找一种独立于操作系统的方式,所以我无法访问/ dev /(u)随机。此外,openssl_random_pseudo_bytes()可能无法使用,所以让我们也忘掉它。在任何情况下,我对性能差异也不感兴趣。

查看phpass库(被许多人使用并被认为足够安全)来生成随机序列,如果/ dev / urandom不可用,则会回溯到以下算法:

// 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

上述算法基本上依赖于getmypid(),md5()和microtime()来生成随机序列。许多人已经指出,时间/ microtime和pid是安全应用程序熵的不良来源,因此即使使用md5和一些字符串操作对它们进行转换,输出也不会“安全随机”。所以我们知道上面的算法最好只有pid和microtime作为熵源。

相比之下,这是另一种算法。鉴于rand是由PHP自动播种的,它(可能)并不比以前的算法更安全,因为rand / mt_rand也默认使用计算机时间和pid(ref)。但由于它不那么复杂,它不是一个更好的选择吗?我还可以重新解释一下这个问题:鉴于上面和下面的算法都依赖于pid和计算机时间来生成随机数,那么上述仍然是优越的,为什么呢?

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;
}

作为最后一个问题,您是否知道在PHP中以独立于操作系统的方式生成随机字节比上述任何方法更好(=更随机)?

3 个答案:

答案 0 :(得分:0)

如果存在操作系统资源,您可以尝试使用这些资源,然后当这些资源不存在而您没有其他选择时,可以回退到自行开发的资源。有关示例,请参阅另一个论坛上的this answer

在支持.NET的Windows系统上,您可以将DOTNET php类与System.Security.Cryptography.RNGCryptoServiceProvider类一起使用。

答案 1 :(得分:0)

如果需要强正确性,请小心依赖OS实现的伪随机生成器。特别适用于安全和模拟。伪随机生成器并不难实现,看一下here的理论和一些参考文献。

答案 2 :(得分:0)

您可以使用的最佳随机数生成器是/dev/random。如果无法访问此界面,那么您可能在Windows系统上,在这种情况下,您可以使用安全性较低的System.Security.Cryptography.RNGCryptoServiceProvider。就输出的随机性而言,函数mt_rand()应该是遥远的第三位。