【问题标题】:Is PHP gmp_random_range function from GMP extension cryptographically secure?GMP 扩展中的 PHP gmp_random_range 函数在密码学上是否安全?
【发布时间】:2025-11-29 02:45:02
【问题描述】:

我使用 PHP 编写了一个生成随机字符组合的软件。为此,我需要随机生成任意长度的整数。所以我使用 GMP 扩展,尤其是 gmp_random_range()。但我需要用一个链接来证明它是加密安全的。或者至少它足够随机。

GMP 随机函数使用种子(gmp_random_seed),如果我不设置种子,一切看起来都足够随机。所以,我想当我没有明确设置种子时,它会从一些可靠的随机源中获取。我找不到明确说明这种情况的内容。

【问题讨论】:

  • 不,gmp 无意加密安全。例如,使用random_intrandom_bytes。一般来说,除非有明确的文档证明适合加密使用,否则它不是。
  • 此外,能够播种 RNG 几乎总是表明密码不安全。 CSPRNG 通常是从操作系统提供的良好来源自动播种的。

标签: php random gmp


【解决方案1】:

"Random State Initialization" 所示,在 GMP 文档中,GMP 中包含的唯一随机生成器算法是——

  • Mersenne Twister 算法,
  • 各种大小的线性同余生成器,以及
  • “无特殊要求的应用程序”的“默认算法”,包括安全要求。

奇怪的是,GMP 文档在"Random State Seeding" 中说,“如果生成的数字将用于重要应用,例如生成加密密钥,那么选择种子的方法至关重要”,即使其中没​​有包含任何算法GMP 适用于加密用途。


您可以在 PHP 中使用random_bytesrandom_int 来生成加密随机数。剩下的唯一事情就是将它们传递的数字转换为任意精度的数字。* 从这个意义上说,GMP 似乎不允许为gmp_random_range 和类似功能自定义 RNG(除了它提供的那些)。因此,您必须借助 GMP​​ 的算术函数“手动”转换这些随机数。我有一个article,它讨论了如何将随机数转换为各种分布。要生成给定范围内的均匀随机整数,您需要的算法在那篇文章中称为RNDINTRNDINTEXC

* 在涉及信息安全的情况下,使用随机数作为非加密 RNG 的种子是不合适的,因为如果给定足够的随机数,攻击者可以向后推导种子,即使种子是以加密方式生成的安全的方式。


如果您的目标只是生成一个加密随机字符串,您甚至不需要走 GMP 路线。只需为要生成的每个字符调用random_int,一次构建一个字符即可:

  • 建立一个允许出现在随机字符串中的字符列表。
  • 对于字符串中的每个字符,调用random_int,最大为列表大小(这个大小几乎肯定在 PHP 可以处理的整数范围内),然后将在给定随机索引处找到的字符附加到列表(从 0 开始)。

【讨论】:

  • 非常感谢您的回答。我会接受它,尽管我不介意其他人也评论这个话题。我想发表更多评论,但我限于 600 个字符。我将包括最后一部分。概括一下:作为我的软件的作者,我应该能够回答生成的组合是否在密码学上安全的问题。我现在可以说的是:“不,他们不是。但随机化是好的(可能是)”。对不起,如果我在这里说了一些愚蠢的话。 (我没有提到 - 我在 Linux 上使用 PHP 7.2)
  • 抱歉继续评论,但知道如何以 CS 方式使用 gmp_random_range。我可以用 random_bytes 的输出播种 GMP RNG,这肯定是 CS。我只需要计算要问多少字节。这取决于我需要来自 gmp_random_range 的数字数量。我已经有了一些公式,它使用对数,而 PHP GMP 没有这样的功能,但我在 SO 中找到了一些解决方案。我想在每次使用之前播种,所以每个结果都是完全随机的。我计划在下周开始实施。目前这只是一个想法。
  • 使用非加密 RNG 的危险在于,如果给定足够的随机数,攻击者可以反向推导种子,即使种子是以加密安全的方式生成的。出于您的目的,特别是如果您正在实施安全敏感算法,您最好直接使用random_bytesrandom_int 给出的数字,而不是使用它们来播种非加密RNG,例如在GMP 中找到的。
  • 谢谢!但我的意思是每次调用 gmp_random_range 时使用不同的种子。所以我会用 random_bytes 来表示随机性,用 gmp 函数来表示它的范围有用性(当然没有 int 类型限制)。我的意思是 - 一颗种子 - 一个数字。我认为攻击者不会有足够的数字。一个是最大值。
  • 从这个意义上说,您是否知道 PHP 的 random_int已经 生成给定整数范围内的加密随机数?另外,我有一个article 讨论如何将随机数转换为各种分布。