我有一个脚本,我在 PHP 中使用 rand 函数。现在我读了一些鬼故事,它们真的很容易预测这些结果。这可以从客户端进行吗?
例如,假设我们有一个rand(0,10)
. 是否可以预测下一个数字?
rand()
函数返回一个伪随机数。这并不意味着next
可以预测数字。然而这张图片可以解释单词的概念pseudorandom
你可以阅读这篇文章
该图像是从一个简单的循环生成的,具有rand
Windows 系统上的功能。
header("Content-type: image/png");
$im = imagecreatetruecolor(512, 512) or die("Cannot Initialize new GD image stream");
$white = imagecolorallocate($im, 255, 255, 255);
for ($y = 0; $y < 512; $y++) {
for ($x = 0; $x < 512; $x++) {
if (rand(0, 1)) {
imagesetpixel($im, $x, $y, $white);
}
}
}
imagepng($im); imagedestroy($im);
这不是那么随机,真的吗?但是现在你知道了……你可以预测下一个数字吗?
真随机数生成器 (TRNG) 和伪随机数生成器 (PRNG) 的区别在于,TRNG 使用不可预测的物理方式生成数字(如大气噪声),而 PRNG 使用数学算法(完全由计算机生成)
[...]
没有多少 PRNG 会产生像这样明显的视觉模式,它恰好是语言 (PHP)、操作系统 (Windows) 和函数 (rand()) 的非常糟糕的组合。
您必须暴力破解 PRNG 的状态。http://crypto.di.uoa.gr/CRYPTO.SEC/Randomness_Attacks_files/paper.pdf
PHP 的 rand() 使用底层标准库实现,这因操作系统而异。
所以第一步,定义操作系统。
下一步,获取 Rand() 函数的源代码和种子代码。
为简单起见,我们假设 PRNG 的种子类似于服务器的毫秒时间。因此,HTTP 请求进来,PHP 播种 PRNG 并执行 rand(0,10)。如果你想预测你会...
将客户端的时钟与服务器的时钟同步,从统计上推导出向服务器发送 HTTP 请求并读取带有时间戳的响应 HTTP 标头的确切时间。
使用您将从服务器请求 rand(0,10) 的预测未来时间播种您的客户端 PRNG(与服务器的实现相同)。在客户端运行 rand(0,10),在确切的未来时间将请求发送到服务器,结果将是相同的。
Ping 时间、处理时间等使这成为一种相当蛮力的方法。
真的,通过互联网(不能直接访问服务器),你不会很幸运地预测 PHP 的 rand() 函数的结果。
从兰德手册:
介于 min(或 0)和 max(或 getrandmax(),包括)之间的伪随机值。
所以,随机不是随机的,而是伪随机的。如果您知道计算是如何完成的,并且知道初始值,则可以预测(计算)下一个值。
如果您需要真正的随机值,则需要其他算法。例如,基于白噪声。
返回的值rand()
只是一个伪随机值。
这意味着,如果您可以访问机器,也许可以计算出这个数字,但这仍然不太可能发生。只看到 PHP 的输出而无法访问机器的最终用户无法选择计算或预测下一个值。一个php脚本的一次执行中的多个rand()
调用的输出可能*技术上*是可预测的,但这不能被使用,因为用户只看到一个整体执行的输出,没有机会在PHP脚本执行时进行交互.
这是用于生成 PHP 种子的过程rand()
:
#ifdef PHP_WIN32
#define GENERATE_SEED() (((long) (time(0) * GetCurrentProcessId())) ^ ((long) (1000000.0 * php_combined_lcg(TSRMLS_C))))
#else
#define GENERATE_SEED() (((long) (time(0) * getpid())) ^ ((long) (1000000.0 * php_combined_lcg(TSRMLS_C))))
#endif
从 PHP 开始4.2.0
, The random number generator is seeded automatically.
我认为您可能想要区分安全和足够安全。关于预测的问题的答案是“是的”,可以预测从伪随机数生成器生成的数字。但是,我认为更重要的问题是这种情况发生的可能性有多大。你想保护什么免受预测?如果您运行的是大型在线游戏网站,那么拥有真正的随机性可能比运行小型 MUD 服务器更重要。它更重要,因为用户破坏模式的后果更严重,并且用户更有可能有动机花时间攻击您的算法。
您可能还想查看 Random.org 的服务。他们提供了一个 API,允许您从他们的服务器中提取真正的随机数。它们从大气噪声中获取熵,至少就您的用户而言,这应该是不可预测的。
不要相信这些鬼故事。对于 webapps,预测是不可能的,下一个数字不能从客户端确定。
为什么?
因为随机数生成器是在每个请求之前播种的,客户端看不到种子值!只有在同一请求中生成所有数字时,预测才有效。