【问题标题】:Making mt_rand() as secure as possible使 mt_rand() 尽可能安全
【发布时间】:2015-07-12 07:09:48
【问题描述】:

我正在编写一个抽奖程序,其中人们有一些门票,这些门票由 1 到 100 范围内的自然数标记。

我用mt_rand(1,100)生成中奖号码,然后输出到网站,大家可以看到。

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

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

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

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

提前致谢:-)

【问题讨论】:

标签: php security random cryptography


【解决方案1】:

简短的回答:

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

您可以简单地使用适合此任务的随机数生成器代替mt_rand()

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

“好的,太好了,但是 PHP 7 还没有发布。我该怎么办今天?”

嗯,你很幸运,你有两个不错的选择。

使用RandomLib。或

我一直致力于将 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. 不要使用模运算符将随机整数减少到一个范围。这将导致有偏的概率分布:
  6. 良好的 CSPRNG 不会退回到不安全的结果。如果没有合适的 CSPRNG 可用,请不要默默地使用 mt_rand();相反,抛出未捕获的异常或发出致命错误。立即引起开发者的注意。

【讨论】:

  • 来自密码学背景,您写的以下句子在我脑海中敲响了警钟:“在撰写本文时,它还没有被清除为稳定版本,但它已经通过了所有人的审查我向安全专家展示过它。”不如告诉我们这些所谓的专家是谁。
  • 当然可以。 CodesInChaos(BLAKE2 作者之一)、SammyK 和 Leigh(参与 PHP 7 CSPRNG 功能的两位作者)、Taylor Hornby(Defuse Security)、Thomas Ptacek、Padraic Brady、Chris Cornutt 和 ##crypto 中的 sarnold。我也向 Anthony Ferrara (ircmaxell) 展示了它,但我不知道他检查它的深度。
  • 实际的审稿人和贡献者名单要长得多。有关更多信息,请参阅 github.com/paragonie/random_compat/issues/11 和自述文件。
  • @TheGreatContini 如果您不满意,请自行查看代码,如果图书馆有什么可以做得更好的地方,请告诉我。 :)
  • “我会将 openssl_random_pseudo_bytes() 作为第一或第二选择。” github.com/paragonie/random_compat/blob/master/ERRATA.md
【解决方案2】:

抱歉,Mersenne Twister 的设计初衷不是为了满足加密要求。不,您不能也不应该尝试修复它,因为通常当非专家尝试改进加密功能时,他们最终只会让事情变得更糟。

PHP 长期以来一直存在用于加密目的的随机性问题。我将指出一些轻读的参考:

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

【讨论】:

【解决方案3】:

mt_rand 顾名思义就是 Mersenne Twister,一个不安全的随机数生成器。此外,它通常只是以毫秒为单位的特定时间播种,攻击者可以简单地猜测或瞄准。

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

您绝对没有理由坚持使用 MT。 PRNG 只是算法。有很多包含安全 PRNG 的库。

【讨论】:

  • “你可以自己编码”——我想说这应该伴随着一个很大的警告。编写一个正确的 PRNG 是困难,而且你可能会搞砸。
  • @SvenSlootweg Maarten 是少数几个我希望能够在不搞砸的情况下写一篇文章的人之一,但我同意这对公众来说是个坏建议。
  • 是的 - 如果不清楚的话,我使用的“你”是对公众的一般建议,而不是对 Maarten 的个人意义 :)
  • @ScottArciszewski 如果您使用现有的安全哈希作为底层函数,则可以减轻(PRNG 的)实施风险,但我同意这作为一般建议可能有点太冒险了。修改后的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-16
  • 2023-01-25
  • 2012-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多