7

我需要在 c++11 中生成加密安全的随机数据,我担心对所有数据使用 random_device 会严重限制性能(参见 Stephan T. Lavavej 的“ rand()被认为是有害的”幻灯片 23,他说当他(在他的系统上)测试它时,random_device 为 1.93 MB/s,mt19937 为 499 MB/s)因为此代码将在移动设备(通过 JNI 和 iOS 的 Android)上运行,这可能比上面的数字慢。

此外,我知道 mt19937 不是加密安全的,来自维基百科:“观察足够数量的迭代(在 MT19937 的情况下为 624,因为这是产生未来迭代的状态向量的大小)允许一个人预测所有未来的迭代”。

考虑到以上所有信息,我是否可以通过每 624 次 mt19937 迭代从 random_device 生成一个新的随机种子来生成密码安全的随机数据?或者(可能)更好的是,每 X 次迭代,其中 X 是 1 到 624 之间的随机数(来自 random_device 或由 random_device 播种的 mt19937)?

4

2 回答 2

7

不要这样做。说真的,只是不要。这不仅仅是自找麻烦——更像是带着大量贵重物品进入你能找到的最危险城市中犯罪最猖獗的地方,自找麻烦。

我建议不要经常尝试重新播种 MT 19937 以掩盖它的不安全性,而是建议通过在计数器模式下运行 AES 来生成随机数。这要求您获得一个(但只有一个)大小合适的良好随机数,以用作您的生成器的初始“种子”。

您将其用作 AES 的密钥,并简单地使用它来加密序列号以获得看起来随机但易于复制的输出流。

这有很多优点。首先,它使用了一种经过大量研究的算法,通常被认为是非常安全的。其次,这意味着您只需要分配一个(相当小的)随机数作为整个系统的“密钥”。第三,它可能提供更好的吞吐量。英特尔和(看似)独立的测试都显示了一系列吞吐量,在低端开始与您对 MT 19937 的报价具有竞争力,而在高端则快约 4-5 倍。鉴于您使用它的方式,我希望看到您获得的结果接近(甚至可能超过1)它们显示的范围的顶端。

底线:计数器模式下的 AES 显然是解决手头问题的更好方法。您可以期望的最好结果是 MT 19937 最终接近于尽可能快且接近于安全。实际上,它可能会让这两个希望都落空,最终变得更慢且安全性大大降低。


1. 它将如何超过这些结果?毫无疑问,这些都是基于对大量数据进行加密——即,从 RAM 中读取数据块,对其进行加密,然后将结果写回 RAM。在你的情况下,你不需要从 RAM 中读取结果——你只需要在 CPU 中生成连续的数字,加密它们,然后写出结果。

于 2015-05-27T06:04:14.090 回答
6

简短的回答是,不,你不能。对加密安全 RNG 的要求非常严格,如果您必须在这里提出这个问题,那么您对这些要求还不够了解。正如 Jerry 所说,如果您需要可重复性,AES-CTR 是一种选择。另一种不允许重复性的选择是为您的系统寻找 Yarrow 或Fortuna的实现。一般来说,在库中找到 CSRNG 比自己创建要好得多。库编写者充分了解良好 CSRNG 的要求。

于 2015-05-27T09:32:30.903 回答