PHP rand()与random_int()

时间:2017-05-28 15:00:31

标签: php php-7

作为http://VM-MASTEr:8088/cluster random_int()函数生成加密安全的伪随机整数

但是,有人可以解释rand()&之间的差异吗? random_int()?只需要一个随机整数时,我可以使用random_int()代替rand()吗?哪一个更快?

6 个答案:

答案 0 :(得分:13)

重新审视这个问题并看到答案已经给出了答案,我发现将评论提交给答案是公平的,因为他们之前已经提交了答案。

PHP 7' random_int()函数的手册说明:

  

"返回加密安全随机整数,范围为min到max(包括)。"

rand()

  

*此功能不会生成加密安全值" *

OP的评论:

  

" @ Fred-ii-谢谢你。但是"加密安全伪随机"意思? - NDFA"

根据我的发现,可以在以下链接中找到:

哪个州:

  

加密安全伪随机数生成器(CSPRNG)或加密伪随机数生成器(CPRNG)[1]是伪随机数生成器(PRNG),其属性使其适用于加密

关于性能,您需要自己运行基准测试。

答案 1 :(得分:8)

从PHP 7.1开始,rand()基本上是mt_rand()的别名。较新的random_int()是三者中最慢但唯一安全的方法。

<?php

$start = microtime(true);
$sum = 0.0;
for ($i = 0; $i < 10000000; $i++) {
    $sum += rand(0, 32767);
}
printf('[rand] Time: %.3f s%s', microtime(true) - $start, PHP_EOL);

$start = microtime(true);
$sum = 0.0;
for ($i = 0; $i < 10000000; $i++) {
    $sum += mt_rand(0, 32767);
}
printf('[mt_rand] Time: %.3f s%s', microtime(true) - $start, PHP_EOL);

$start = microtime(true);
$sum = 0.0;
for ($i = 0; $i < 10000000; $i++) {
    $sum += random_int(0, 32767);
}
printf('[random_int] Time: %.3f s%s', microtime(true) - $start, PHP_EOL);

结果:

[rand] Time: 10.973 s
[mt_rand] Time: 9.628 s
[random_int] Time: 23.069 s

答案 2 :(得分:3)

作为大多数数字生成器,使用rand()是不安全的,因为它不会生成加密安全值,并且rand()的输出是可预测的。

PHP 7.0引入了random_bytes和random_int作为核心函数,它们没有大多数随机数生成器所具有的问题。

答案 3 :(得分:1)

rand()

rand()现在是mt_rand()的别名。观察source code of mt_rand(),可以看出随机数根本不是随机的。这是一个简单的数学计算,没有比

复杂的多
return $min + suffle_bits($internal_counter++) % ($max - $min);

其中suffle_bits()是一些可预测的二进制算法,使它看起来像$internal_counter并不只是在增加自身。

这就是为什么说rand()返回伪随机数字的原因。返回的数字似乎是随机绘制的,但是知道$internal_counter的值可以让您预测接下来的情况。

random_int()

random_int()不会受到此可预测性问题的困扰,只要计算机的熵生成器已正确启动即可。

即使攻击者收集了大量值,也无法猜测下一个值。

哪个是最好的

如果攻击者可以从代码输出中猜测$internal_counter的值,并利用该知识来干扰代码的预期用途,请使用random_int()

如果使用随机数显示(例如随机问候),那么rand()是绝对安全的。

现在,如果必须生成一长串GUID或条形码,并且最终用户必须不能从子集中猜出另一个有效值,那么random_int()不仅对安全性有好处,还因为它不会不再重复。根据平台的不同,rand()可能会以32768的输出速度迅速重复自身。

哪个更快?

毫无疑问,rand()更简单,因此也更快。

这是一个粗略的单行易复制/粘贴命令,用于计算在10秒内可以从rand()提取多少个数字:

php -r '$s=microtime(true);$c=0;while(microtime(true)-$s<10){rand(0,9);$c++;};echo "$c\n";'

random_int()相同:

php -r '$s=microtime(true);$c=0;while(microtime(true)-$s<10){random_int(0,9);$c++;};echo "$c\n";'

php 7.3的计数器为:

rand():       36665142
random_int(): 10511327

rand()的速度不到4倍。除非速度不成问题,否则random_int()是必经之路,但对于最基本的非关键任务而言。

答案 4 :(得分:0)

我个人使用random_int并没有遇到任何问题,但是应该将其与try / catch一起使用,因为如果无法收集足够的熵,它将引发异常。

答案 5 :(得分:0)

补充 Frédéric 响应,在 PHP 8.0.3 中,random_int() 似乎比以前快了很多,使用他自己的代码示例。

与:

<?php
    echo "this will take 20 seconds\n\n";
    
    echo "generating random with 'rand' method\n";
    $s1=microtime(true);$c1=0;while(microtime(true)-$s1<10){rand(0,65535);$c1++;};
    $fc1 = number_format($c1 , 0, ',', '.');
    echo "generated: $fc1\n\n";
    
    echo "generating random with 'random_int' method\n";
    $s2=microtime(true);$c2=0;while(microtime(true)-$s2<10 {random_int(0,65535);$c2++;};
    $fc2 = number_format($c2 , 0, ',', '.');
    echo "generated: $fc2\n\n"; 
?>

我得到了输出:

this will take 20 seconds

generating random with 'rand' method
generated: 48.423.988

generating random with 'random_int' method
generated: 30.843.067

在他的测试中,random_int()rand() 慢三倍多。

在这些中,random_int() 仅比 rand() 慢 40%。

PS:我将最大随机值从 9 增加到 65535 供个人使用,似乎实际上提高了两种情况的速度。