【问题标题】:XOR with another value after every round of xorshift RNG?在每轮 xorshift RNG 之后与另一个值异或?
【发布时间】:2014-03-06 04:26:35
【问题描述】:

Xorshift 和所有 LFSR 类型的生成器如果将其设为全零状态,则会停止运行并且什么也不做。看起来(如果我的测试中没有错误),以下功能:

y = one_xorshift_round(y)
y = y ^ key

将抵抗这种锁定,因为 y 的任何非零状态都会对某个随机值产生变化,并且任何为零的状态都将通过密钥与其他值进行异或。如果密钥导致它落在零上,它会在下一轮修复它。

我想您还会获得每个“键”值产生不同序列的额外好处。

我的应用程序是一个 Arduino 库,它需要统计上的随机数,这些随机数根本不需要任何加密强度,但不能一遍又一遍地重复相同的循环。我想要做的是使用板子上电以来的当前微秒计数作为密钥,这应该在每次使用 RNG 时增加一点熵(由于用户造成的事情的确切时间不确定性输入等),并且还会导致随机序列随着时间的推移而不同,有点人为地伪造具有更大的周期。

我的问题是,是否有一些键值或变量键的简单模式会导致 XORSHIFT 生成器做一些坏事,比如进入一个短周期?我想实际计算出来的数学会非常复杂,但也许有人参考了一篇论文或类似修改过的 RNG 的东西?

谢谢!

编辑,附加信息:我对全零状态问题的第一反应是每轮都向状态添加 1,但我发现向状态添加一个常数会减少周期的数量,该数量随不变,但似乎没有任何简单的模式。

【问题讨论】:

  • 为什么不将状态初始化为非零值,并使用最大长度的 LFSR,而不是尝试自己发明?
  • 主要是因为我希望能够定期将新熵异或到状态中,以随着时间的推移提高质量,并且对全零状态的测试看起来很丑陋,而且还因为能够改变的理论上的好处“关键”并得到一个完全不同的序列。但如果没有人听说过任何论文或任何东西,我可能会听从你的建议,即使播种会延迟启动。
  • Xorshift 生成器也存在于更大的变体中,例如在原始论文中有一个版本 (xor128()),其中状态由四个 uint32(并非全为零,周期 2^128)组成;在我的电脑上 12 个额外的字节不是问题,它和简单的 xorshift 一样快——在 Arduino 上不知道 :)
  • @EternityForest 最大长度 LFSR 生成单个序列,该序列生成每个可能的输出数。任何引入“弱键”的修改都会缩短最大长度。如果您担心引入更多熵,您可能不应该使用像 LFSR 那样弱且可预测的 PRNG。

标签: random cryptography arduino prng


【解决方案1】:

键会导致短周期的最简单情况是键是独占或一个值及其来自原始生成器的连续值。这将具有将状态重置为其先前值的效果,因此它只能产生一个输出。

如果原始生成器的许多不同输出对的该键值相同,那么这将代表随机性测试的严重失败,因此更有可能存在许多不同的值可以有效地将循环中的一个阶段退回在该周期的不同时间点。

因此,假设您的密钥的许多值可以通过最终将生成器困在单值轨道中来缩短生成器的周期,这可能是公平的。然后是更复杂的情况,导致更长的轨道仍然不是完整的周期,但这些更难考虑。

您可能想要做的是分别收集熵并使用它来调整 PRNG 的输出,而不会破坏 PRNG 本身的质量。例如,

void add_entropy(uint32_t more)
{
    entropy = one_xorshift_round(entropy + more);
}

uint32_t rand(void)
{
    y = one_xorshift_round(y);
    return one_xorshift_round(y + entropy);
}

【讨论】:

  • 是的,作为键的两个连续状态的 XOR 与您所说的完全一样。我想“弱键”相当少见,但显然确实存在。永远不会想到这一点。
  • 嗯,通过异或不同的连续状态对找到的每个新值都是一个新的弱密钥。如果随机数生成器很好,那么你会发现很多弱密钥;因为如果 RNG 的连续输出的异或限制为一小组值,那么 RNG 太可预测了。
  • 嗯,xor shift 不是加密的,而且我没有找到很多弱密钥,所以要么我的代码中存在错误......要么 xorshift 没有那么多可能性(n)^s(n-1) 如您所想。我确实发现 XORing 的值会增加每个周期(这不应该导致相同的短暂影响)提高了顽固的分数,但代价是使整个事情变得非标准,这似乎是一个可以接受的权衡非安全相关的东西。我想我会以一个不变的想法放弃 XOR,但在美国的时间 XOR 似乎没问题,除非有理由不这样做。
  • 哦。我想 xorshift 在这方面很弱应该不足为奇。无论如何,由于循环扰动很难证明是安全的,我建议像我的示例代码中那样使用循环外扰动。另外,我建议使用 add 而不是 xor,因为 add 具有一些 xor 无法自行管理的位扩展优势。这应该会进一步提高顽固分子的分数。
  • 哇!在我基于 PC 的测试中,向状态添加一个伪造的 micros() 值(通过假设任何两次调用之间经过 1234uS 来伪造)导致通过每个顽固的测试,周期约为 29 亿(每个计数器值不同,有些增加它)我也喜欢循环外的想法。我并不特别担心周期,因为在真正的应用程序中 micros() 基本上是随机的,这是针对内置在 UART 协议栈中的 RNG,因此会有网络流量需要重新播种。另外,即使周期只有 1000 万,大多数 Arduino 应用程序也不会注意到。
【解决方案2】:

我不会过多地使用随机生成器(比如任意改变状态空间),因为它良好的统计特性可能会消失。

测试种子不是全零一点都不错:这是在每个此类生成器中所做的。如果你想注入熵,只需在状态空间上异或你的熵位,如果你得到全零,只需输入一些常数。如果状态空间足够大,那么概率就会很低,以至于您输入的内容不相关。在这种情况下,许多已发布的生成器使用生成器的名称(作为 ASCII 值序列)来为生成器播种! :)

不过,我建议您尝试一些 64 位变体,例如 xorshift*/xorshift+,因为它们比纯 xorshift 生成器具有更好的统计属性。您可以在http://prng.di.unimi.it/

找到最新报告

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-24
    • 1970-01-01
    相关资源
    最近更新 更多