我需要在 c++11 中生成加密安全的随机数据,我担心对所有数据使用 random_device 会严重限制性能(参见 Stephan T. Lavavej 的“rand() Considered Harmful”幻灯片 23,他说当他(在他的系统上)测试它时,random_device 是 1.93 MB/s 而 mt19937 是 499 MB/s)因为这段代码将在移动设备(Android 通过 JNI 和 iOS)上运行,这可能比上面的数字慢。
此外,我知道 mt19937 不是加密安全的,来自 wikipedia :“观察足够数量的迭代(在 MT19937 的情况下为 624,因为这是产生 future 迭代的状态 vector 的大小)允许预测所有 future 的迭代”。
考虑到上述所有信息,我可以通过每 624 次 mt19937 迭代从 random_device 生成一个新的随机种子来生成加密安全的随机数据吗?或者(可能)更好的是,每 X 次迭代,其中 X 是 1 到 624 之间的随机数(来自 random_device 或由 random_device 播种的 mt19937)?
最佳答案
不要这样做。说真的,只是不要。这不仅仅是自讨苦吃,更像是带着许多贵重元素进入你能找到的最危险城市中犯罪率最高的地区,这是自讨苦吃。
与其尝试频繁地重新播种 MT 19937 以掩盖它的不安全性,我建议您通过在计数器模式下运行 AES 来生成随机数。这需要您获得一个(但只有一个)大小合适的随机数,用作生成器的初始“种子”。
您将其用作 AES 的 key ,并简单地使用它来加密序列号以获得看似随机但易于重现的输出流。
这有很多优点。首先,它使用的算法实际上已经过大量研究,并且通常被认为是非常安全的。其次,这意味着您只需分配一个(相当小的)随机数作为整个系统的“ key ”。第三,它可能提供更好 的吞吐量。两者 Intel's和(貌似)independent tests显示一系列吞吐量,这些吞吐量开始与您在低端为 MT 19937 报价时具有竞争力,而在高端则快 4-5 倍左右。鉴于您使用它的方式,我希望看到您得到的结果接近(甚至可能超过 1)它们显示的范围的顶端。
底线:计数器模式下的 AES 显然是手头问题的更好解决方案。您可以希望的最好结果是 MT 19937 最终接近同样快速和接近安全。实际上,它可能会让这两个希望都落空,并最终变得更慢且安全性大大降低。
<子> 1. 它如何超越那些结果?这些无疑是基于加密批量数据——即从 RAM 中读取数据 block ,对其进行加密,然后将结果写回 RAM。在你的情况下,你不需要从 RAM 中读取结果——你只需要在 CPU 中生成连续的数字,加密它们,然后写出结果。
关于c++ - 我可以通过重新播种结合 random_device 和 mt19937 生成加密安全随机数据吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30473376/