PHP rand() 与 random_int()
Posted
技术标签:
【中文标题】PHP rand() 与 random_int()【英文标题】:PHP rand() vs. random_int() 【发布时间】:2017-10-28 22:47:50 【问题描述】:作为php.net indicates: random_int()
函数生成加密安全的伪随机整数。
但是,有人能解释一下rand()
和random_int()
之间的区别吗?当只需要一个随机整数时,我可以使用random_int()
而不是rand()
吗?哪个更快?
【问题讨论】:
php.net/manual/en/function.random-int.php "返回一个加密的安全随机整数,范围从 min 到 max,包括。" 和 php.net/manual/en/function.rand.php "此函数不生成加密安全值” en.wikipedia.org/wiki/… --- ***.com/questions/2449594/… 使用rand()
,除非你需要一个安全的随机整数,然后使用random_int()
。如果你不知道你是否需要后者,你可能不需要(它会影响“可猜测性”,所以想象一下它在哪里有用)。例如,如果您尝试随机播放幻灯片,rand()
就可以了。
关于速度的事情,除非你知道你需要它,否则不要在此基础上过早优化。专注于函数的应用,然后在必要时调整效率。
mt_rand()
在 PHP 7.1 中取代了 rand()
。只是想知道为什么没有提到?
【参考方案1】:
重新审视这个问题并看到给出的答案,我发现我将我的 cmets 提交给一个答案是公平的,因为他们之前已经提交过。
PHP 7 的 random_int()
函数手册指出:
http://php.net/manual/en/function.random-int.php“返回从 min 到 max 范围内的加密安全随机整数。”
对于rand()
http://php.net/manual/en/function.rand.php*此函数不生成加密安全值" *
OP 的评论:
“@Fred-ii- 谢谢。但是“加密安全伪随机”是什么意思?- NDFA”
根据我的发现,可以在以下链接中找到:
https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator其中规定:
加密安全伪随机数生成器 (CSPRNG) 或加密伪随机数生成器 (CPRNG)[1] 是一种伪随机数生成器 (PRNG),其特性使其适用于密码学.
How does a cryptographically secure random number generator work?
关于性能,您需要自己运行基准测试。
【讨论】:
我同意。很高兴将您的答案作为参考留在这里(因为我认为随着 php 开发人员切换到 7 这个问题会引起更多关注)。 确实@NDFA 干杯【参考方案2】:从 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);
PHP 7.4 的结果:
[rand] Time: 0.320 s
[mt_rand] Time: 0.326 s
[random_int] Time: 9.255 s
【讨论】:
【参考方案3】: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】:与大多数数字生成器一样,使用 rand() 并不安全,因为它不会生成加密安全值,而且 rand() 的输出是可预测的。
PHP 7.0 引入了 random_bytes 和 random_int 作为核心函数,解决了大多数随机数生成器存在的问题。
【讨论】:
那是错误的。首先,这不是问题,它是设计使然,像 rand() 这样的加密不安全函数通常比加密安全函数快,所以如果你不将它用于与安全相关的事情,最好使用非安全函数。您无法真正比较加密安全和加密不安全的功能,它们的用法确实不同。【参考方案5】:我个人在使用 random_int 时没有遇到任何问题,但它应该与 try/catch 一起使用,因为如果无法收集足够的熵,它会引发异常。
【讨论】:
【参考方案6】:补充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 以供个人使用,似乎实际上提高了两种情况的速度。
【讨论】:
以上是关于PHP rand() 与 random_int()的主要内容,如果未能解决你的问题,请参考以下文章
关于PHP中array_rand函数为啥不能只设置一个随机?