关于安全性:更好地随机生成PHP

关于安全性:更好地随机生成PHP

Better Random Generating PHP

我知道仅使用rand()是可以预见的,如果您知道自己在做什么,并且可以访问服务器。

我有一个项目高度依赖于选择一个尽可能不可预测的随机数。因此,我正在寻找可以生成更好的随机数的其他内置函数或用户函数的建议。

我用它来做一些测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$i = 0;

while($i < 10000){
    $rand = rand(0, 100);

    if(!isset($array[$rand])){
        $array[$rand] = 1;
    } else {
        $array[$rand]++;
    }

    sort($array);
    $i++;
}

我发现结果是均匀分布的,每个数字生成的次数有一个奇怪的规律。


添加,相乘或截断不良的随机源将给您不良的随机结果。有关说明,请参见随机性和随机数简介。

您对PHP rand()函数是正确的。引人注目的插图,请参见统计分析的第二个图。 (第一个数字引人注目,但它是由Scott Adams绘制的,未使用rand()绘制)。

一种解决方案是使用真正的随机生成器,例如random.org。另一个,如果您使用的是Linux / BSD / etc。是使用/ dev / random。如果随机性是关键任务,则必须使用硬件随机数生成器。


random.org具有可以通过HTTP访问的API。

RANDOM.ORG is a true random number service that generates randomness
via atmospheric noise.


我会对随机性的印象保持警惕:在许多实验中,人们会选择随机性较低的分布。似乎头脑不太擅长产生或估计随机性。

Fourmilab上有很多关于随机性的文章,包括另一篇真正的随机发生器。也许您可以从这两个站点获取随机数据,所以如果一个站点出现故障,您仍然可以拥有另一个站点。

Fourmilab还提供了一个测试程序来检查随机性。您可以使用它来检查各种myRand()程序。

对于最后一个程序,如果生成10000个值,为什么不从1万个中选择最终值呢?您将自己限制为一个子集。另外,如果您的$ min和$ max大于10000,则将不起作用。

无论如何,您需要的随机性取决于您的应用程序。 rand()对于在线游戏来说是可以的,但对于密码术来说则是不可行的(任何未经统计程序彻底测试的东西都将不适合于密码学)。您是法官!


获取随机数的另一种方法,其概念类似于获取UUID

PHP版本5.3及更高版本

1
openssl_random_pseudo_bytes(...)

或者您可以使用RFC4122尝试以下库


@KG上的变化,使用自EPOCH以来的毫秒数作为兰特的种子?


一个新的PHP7,有一个功能可以完全满足您的需要:它会生成加密安全的伪随机整数。

1
int random_int ( int $min , int $max )

Generates cryptographic random integers that are suitable for use
where unbiased results are critical (i.e. shuffling a Poker deck).

有关PRNG和CSPRNG(及其区别)以及为什么您的原始方法实际上不是一个好主意的更详细说明,请阅读我的另一个非常相似的答案。


推荐阅读