今天我想:好吧,即使对RANDt的NIST SP 800-90A实现有很大的怀疑,它仍然是伪随机数生成器(PRNG)的硬件实现,对于非敏感应用程序必须足够好。因此,我想到了在游戏中使用它而不是Mersenne Twister。
因此,要查看使用该指令是否可以获得任何性能提升,我比较了以下两个代码的时间:
// test.cpp
#include <cstdio>
int main()
{
unsigned int rnd = 0;
for(int i = 0; i < 10000000; ++i) {
__builtin_ia32_rdrand32_step(&rnd);
}
printf("%x\n", rnd);
}
和
//test2.cpp
#include <cstdio>
#include <random>
int main()
{
unsigned int rnd = 0;
__builtin_ia32_rdrand32_step(&rnd);
std::mt19937 gen(rnd);
for(int i = 0; i < 10000000; ++i) {
rnd ^= gen();
}
printf("%x\n", rnd);
}
通过运行两个我得到:
$ time ./test
d230449a
real 0m0.361s
user 0m0.358s
sys 0m0.002s
$ time ./test2
bfc4e472
real 0m0.051s
user 0m0.050s
sys 0m0.002s
因此,在我的CPU上,Mersenne Twister比RDRAND快得多。好吧,我很失望,被排除在比赛之外。但是RDRAND是一种加密安全的PRNG(CSPRNG),因此它在幕后发挥了很多作用……更公平的是,可以将其与其他CSPRNG进行比较。因此,我采用了Rabbit实现(将RFC转换为C,没有花哨的性能技巧),并编写了以下测试:
// test3.cpp
#include <cstdio>
extern "C"
{
#include "rabbit.h"
}
int main()
{
rabbit_state s;
unsigned long long buf[2];
__builtin_ia32_rdrand64_step(&buf[0]);
__builtin_ia32_rdrand64_step(&buf[1]);
rabbit_init_key(&s, (uint8_t*)&buf[0]);
for(int i = 0; i < 10000000; ++i) {
rabbit_extract(&s, (uint8_t*)&buf[0]);
}
printf("%llx\n", buf[0]);
}
令我惊讶的是,生成的伪随机数据是前两个伪随机数据的两倍,我得到了比RDRAND更好的时间:
$ time ./test3
8ef9772277b70aba
real 0m0.344s
user 0m0.341s
sys 0m0.002s
所有这三个都在启用优化的情况下进行了编译。
因此,我们普遍认为RDRAND是将NSA后门程序嵌入到每个人的软件密码中的。另外,我们至少有一种软件CSPRNG比RDRAND快,而使用最广泛的体面的PRNG Mersenne Twister比RDRAND快得多。最后,我们有开源可审计的软件熵池,例如
/dev/random
和/dev/urandom
,它们没有隐藏在AES的双重加扰器层(如RDRAND)的后面。所以,问题是:人们应该使用RDRAND吗?有合法用途吗?还是我们应该完全停止使用它?
最佳答案
如in the other answer所指出的那样,RDRAND的种子是真正随机的。特别是,它经常使用128位硬件生成的随机性来重新播种其内部CSPRNG,从而确保每511 * 128位至少重新播种一次。请参阅本文件第4.2.5节:
https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide
因此,在您的示例中,您使用了一个128位种子来从rabbit_extract生成1000万次随机抽取。在RDRAND版本中,相当于进行了250万次128位绘制,这意味着CSPRING至少播种了2,500,000/511 = 4,892次。
因此,在您的Rabbit示例中,没有代替128位熵,而在RDRAND示例中,至少有4,892 * 128 = 626,176位熵。
这比没有硬件支持在0.361秒内获得的熵要多得多。如果您正在做很多真正随机性很重要的事情,那可能很重要。一个示例是Shamir secret 共享大量数据-不确定是否还有其他数据。
因此,总而言之,这不是为了速度,而是为了提高安全性。它是否是后门程序的问题当然很麻烦,但是您始终可以将它与其他来源进行XOR,至少起码不会对您造成伤害。
关于random - 英特尔的RDRAND有合法用途吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26771329/