今天我想:好吧,即使对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/

10-11 18:43