【问题标题】:OS-independent random byte sequence in PHPPHP中与操作系统无关的随机字节序列
【发布时间】:2011-11-05 12:31:52
【问题描述】:

我想生成一个随机字节序列以在安全敏感的上下文中使用。我正在寻找一种独立于操作系统的方式,所以我无法访问 /dev/(u)random。此外, 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()来生成随机序列。许多人已经指出,时间/微时间和 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 中以独立于操作系统的方式生成随机字节的更好(=更随机)方式吗?

【问题讨论】:

  • 在 PHP 中没有可移植且始终可用的方法来生成加密强的随机字节序列。你需要一个特定的环境或可用的工具,你的先决条件排除了这些。 -- phpass 仅使用 rand 或哈希解决方法的原因是它仅将其用作密码盐,这不依赖于高熵。
  • 我明白,如果没有操作系统支持,我将无法生成加密安全的随机序列。但是我展示的第二个算法与第一个算法相比如何,(为什么)其中一个比另一个更好?
  • mt_rand 和 rand 已经播种,您实际上是通过减少种子的熵来降低这些函数的安全性。
  • 第一个算法似乎也有类似的种子。如果我删除了 RandomBytes() 中的种子部分,会有什么变化吗?

标签: php security random


【解决方案1】:

如果存在操作系统资源,您可以尝试使用它们,然后在这些资源不存在且您别无选择时回退到自有资源。有关示例,请参见另一个论坛上的 this answer

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

【讨论】:

    【解决方案2】:

    如果需要高度正确性,请小心依赖操作系统实现的伪随机生成器。专门用于安全和模拟。伪随机生成器实现起来并不难,看看here 了解一些理论和一些参考资料。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-08-27
        • 1970-01-01
        • 2013-08-29
        • 1970-01-01
        • 2017-08-30
        • 2013-09-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多