更好的随机生成PHP

22

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

我的项目高度依赖于选择尽可能不可预测的随机数。因此,我正在寻求建议,无论是其他内置函数还是用户函数,都可以生成更好的随机数。

我用这个来进行一个小测试:

$i = 0;

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

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

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

我发现结果分布均匀,但每个数字生成的次数有一种奇怪的模式。


在php7中有一个新的函数,它正好做你需要的事情 - Salvador Dali
6个回答

22

当你使用低质量的随机源进行加法、乘法或截断操作时,会得到一个低质量的随机结果。请参阅《随机性与随机数介绍》进行解释。

关于 PHP 的 rand() 函数,你是正确的。请看统计分析中的第二张图像,它有一个惊人的说明。(第一张图也很惊人,但那是 Scott Adams 画的,并不是用 rand() 绘制的。)

如果想要解决这个问题,一种方法是使用真正的随机生成器,比如random.org。如果你正在使用 Linux/BSD 等操作系统,则可以使用/dev/random。如果随机性对任务至关重要,你将不得不使用硬件随机生成器


5

random.org提供HTTP接口,可用于访问。

RANDOM.ORG是一个真正的随机数服务,通过大气噪声生成随机性。


4
我建议你对随机性的印象保持警惕: 有许多实验表明人们会选择较不随机的分布。看来大脑并不擅长产生或估计随机性。
Fourmilab上有关于随机性的好文章,包括另一个真正的随机生成器。也许你可以从这两个网站获取随机数据,这样如果其中一个出现问题,你仍然有另一个。
Fourmilab还提供了一个测试程序来检查随机性。你可以用它来检查你的各种myRand()程序。
至于你最后一个程序,如果你生成10000个值,为什么不从这10000个值中选择最终值呢?你把自己限制在了一个子集中。而且,如果$min和$max大于10000,它将无法工作。
无论如何,你需要的随机性取决于你的应用。rand()对于在线游戏来说可能还可以,但对于加密来说就不行了(任何没有经过统计程序彻底测试的东西都不适合用于加密)。你自己来判断吧!

1
关于您所提到的真随机生成器:在2022年底,HotBits放射性随机数生成器服务将被停用。 - RWC

2

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

PHP 5.3及以上版本

openssl_random_pseudo_bytes(...)

您可以尝试使用遵循RFC4122标准的

1

在@KG的基础上进行变化,使用自纪元以来的毫秒数作为rand函数的种子?


所以,随着今天快速的多核计算机,你有很大的机会多次重复使用种子?这是一个巨大的警告信号 - 你正在重新发明轮子,即使没有参数的srand()也能做得更好(“更随机”)。 - Piskvor left the building

1

有一个新的PHP7函数,可以完全满足你的需求:它生成密码学安全的伪随机整数。

int random_int ( int $min , int $max )

生成适用于需要无偏结果的加密随机整数(例如洗牌扑克牌)。

有关 PRNG 和 CSPRNG 的更详细解释以及它们之间的区别,以及为什么您的原始方法实际上是一个坏主意,请阅读我的 另一个高度相似的答案


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接