【问题标题】:Seeding pseudo random generator with random number from a better random source使用来自更好随机源的随机数播种伪随机生成器
【发布时间】:2017-05-25 11:44:24
【问题描述】:

假设我们有一个伪随机数生成器,它接受一个 32 位整数作为种子(例如 C 标准库中的 rand() 函数),它从原始种子派生随机数。如果该种子来自放射性衰变,假设我们通过调用rand() 得到的随机数与从放射性衰变中生成随机数一样“好”随机数是否正确?

【问题讨论】:

  • 您是否在问从衰变中播种是否比从程序启动以来的滴答声中播种更好?
  • 第一个数字是好的,当随机数生成器不去除熵时(例如,当种子为 32 位时,生成器应该能够输出所有可能的 2^32 值(而不是 e. .g 通过丢弃到高 16 位只有 2^16 个))。但是除非种子重新充满熵,否则随后生成的数字的质量会越来越低。
  • @UnTraDe 新数字不会包含超过 32 位的熵。
  • @OliverCharlesworth 您可以轻松地将一个非常糟糕的随机数生成器定义为x = x + 1。然后尝试用一个真正的随机数播种它。据你说,“整个序列现在是随机的”。实际上,由于初始种子是真正随机的,因此无法预测哪个将是您的伪随机序列的第一个数字,但它会像现在一样糟糕:序列根本不会是随机的。跨度>

标签: c++ c security random entropy


【解决方案1】:

不,绝对不是。 C/C++ 标准库的内置rand() 函数通常实现为linear congruential generator (LCG)。它是已知最早的伪随机数生成器 (PRNG) 家族之一,并且它们通常具有臭名昭著的不良统计特性。此外,由于 PRNG 实际上会产生一个由初始种子预先确定的数学序列,因此它们是可预测的。即使是加密安全的伪随机数生成器(如Blum Blum Shub)也是可预测的,即使预测序列计算困难且非常耗时。

相比之下,基于放射性衰变的随机数发生器是真正的随机数发生器。生成的数字序列完全均匀分布且不可预测,样本之间没有任何可测量的相关性。

回到伪随机数,初始种子源的统计质量并不能提高生成的伪随机序列的统计质量——它只取决于生成器本身。如果您使用真正的随机数作为 PRNG 的种子,那么序列的第一个数字将是不可预测的,但随后序列的质量将与没有真正随机种子的情况相同。

如果您想要高质量的随机性,则必须使用高质量的随机数生成器。有一些具有出色统计特性的伪随机数生成器(绝对不是著名的Mersenne Twister),通过了所有当前的随机性统计测试 - 虽然生成的伪随机序列仍然是可预测的,但在统计上很难与真正的随机序列。

现代随机数生成器的可靠资源是Sebastiano Vigna's website

【讨论】:

    【解决方案2】:

    随机数的质量取决于随机数生成器的质量。产生伪随机数的方法有很多种,您选择的那一种应该适合您的应用,但老实说,如果您可以使用无线电活性衰减监测设备,那么您可能能够访问真正的随机数(来自其他一些完全随机的现实世界事件),而不是播种一个伪事件。

    【讨论】:

    • 但是无论算法是什么,随机种子肯定会影响结果,对吧?假设伪算法是“s+n+1”,其中 s 是种子,n 是要生成的数字的索引,1 是一个常数。您使用数字 896 为该算法播种,该数字是通过监测放射性衰变生成的,那么该算法输出的第一个数字是 897,这与种子数字一样难以/不可能猜测。使用该算法生成的后续数字无需重新播种将非常容易预测,但第一个不是?
    • 只要你总是用不同的(随机)数字播种,那么来源就无关紧要了。只要有人类交互,就会有可变性,所以我怀疑使用衰减方法生成种子是否比某人单击 UI 启动程序需要多长时间更好。当然,如果这是一个总是在午夜重新启动的服务器,并且您将一天开始以来的滴答作为您的种子,这将不是一个好方法。
    • @UnTraDe 您的假设在您的评论中是正确的。如果您的初始种子是真正随机的,则无法预测序列的第一个数字(因为第一个数字仅取决于该真正的随机数,没有任何先前的状态)。然而,后续数字的质量由伪随机数生成器决定。
    【解决方案3】:

    。随机数序列的性质完全取决于随机数生成器(RNG)。因此,后续随机数之间的任何相关性都取决于 RNG 而不是种子。

    不过,话虽如此,种子对于避免在不同运行代码时生成的序列之间的相似性很重要。因此,您应该始终尝试使用真正随机的种子来播种您的 RNG。

    【讨论】:

      【解决方案4】:

      伪随机数(PRN)可能是一个接近随机数的序列。然而,真正的随机数 (TRN) 是通过从 熵源 获取输入来生成随机数的那些,它可以是从振动到硬盘活动的任何类型的物理环境。 C库的rand()属于PRN的范畴。对于高随机性,最好使用使用 /dev/random 或 /dev/urandom 的库。

      有关随机、urandom - 内核随机数源设备的更多详细信息,请参阅 urandom 的联机帮助页,地址为 https://linux.die.net/man/4/urandom“随机数生成器将来自设备驱动程序和其他来源的环境噪声收集到一个熵池中。生成器还保持对熵池中噪声位数的估计。从这个熵池中创建随机数。”

      【讨论】:

        猜你喜欢
        • 2011-02-08
        • 2015-03-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-15
        • 2010-11-01
        • 2015-08-07
        相关资源
        最近更新 更多