使mt_rand()尽可能安全

时间:2015-07-12 07:09:48

标签: php security random cryptography

我正在写一个抽奖程序,人们有一些门票,标有1到100的自然数字。

我使用mt_rand(1,100)生成中奖彩票的编号,然后将其输出到网站,这样每个人都可以看到它。

现在我做了一些研究,并从Merseene wiki文章中发现:

观察足够数量的迭代(在MT19937的情况下为624,因为这是生成未来迭代的状态向量的大小)允许人们预测所有未来的迭代。

mt_rand()MT19937使用的当前版本是什么?

如果是这样,我该怎么做才能使我生成的数字在加密方面更加安全?

提前致谢: - )

3 个答案:

答案 0 :(得分:11)

答案简短:

  

如果是这样,我该怎么做才能使我生成的数字在加密方面更加安全?

您只需使用适合此任务的随机数生成器而不是mt_rand()

当PHP 7问世时,如果需要加密安全的随机数生成器,您可以在项目中使用random_int()

"好的,很好,但PHP 7还没有结束。我该怎么做今天?"

嗯,你好运,你有两个很好的选择。

使用RandomLib。 OR

我一直致力于将PHP 7的CSPRNG功能反向移植到PHP 5项目中。它位于paragonie/random_compat下的Github上。

"我不想使用图书馆;我该如何安全地自己滚动?"

在加密方面,滚动自己的实现通常是一个糟糕的决定。 "不是在这里发明的,"通常是一件好事。但是,如果您已经将自己的PHP库编写到securely generate random integers or strings,那么请记住以下几点:

  1. 使用可靠的随机来源。在order of preference中,从/dev/urandom读取应该是您的首选,然后是mcrypt_create_iv() MCRYPT_DEV_URANDOM,然后是CAPICOM(仅限Windows),最后是openssl_random_pseudo_bytes()
  2. /dev/urandom读取时,缓存文件描述符以减少每个函数调用的开销。
  3. /dev/urandom读取时,PHP将始终缓冲8192个字节的数据(可能您不会使用)。请务必关闭读取缓冲(即stream_set_read_buffer($fileHandle, 0);)。
  4. 避免任何可能泄漏计时信息的功能或操作。通常,这意味着您希望使用按位运算符而不是数学函数(例如log())或涉及浮点数的任何内容。
  5. 不要使用模运算符将随机整数减少到一个范围。这将导致有偏差的概率分布: Biased distribution proof-of-concept
  6. 好的CSPRNG不会回退到不安全的结果。如果没有合适的CSPRNG,请不要默默使用mt_rand();相反,抛出未捕获的异常或发出致命错误。立即引起开发人员的注意。

答案 1 :(得分:1)

mt_rand的名字是Mersenne Twister,一个非安全的随机数发生器。此外,它通常仅以ms为特定时间播种,这是攻击者可以简单猜测或瞄准的目标。

你无法确保Mersenne Twister的安全。因此,如果可能的话,您应该使用由熵源播种的安全随机数发生器。该熵源通常从操作系统获得。应首选基于OpenSSL的。

绝对没有理由为什么你会被MT困住。 PRNG只是算法。有很多库包含安全的PRNG。

答案 2 :(得分:1)

很抱歉,但Mersenne Twister并非旨在满足加密要求。不,你不能也不应该试图修复它,因为通常当非专家尝试改进加密功能时,他们最终会使事情变得更糟。

Php在加密目的的随机性问题上有很长的历史。我会指出一些关于光读的参考文献:

据我所知,PhP应用程序中安全(伪)随机数生成的最佳选择是使用openssl_random_pseudo_bytes