今天我想:嗯,即使对NIST SP 800-90A的RDRAND实现有很大的怀疑,它仍然是伪随机数生成器(PRNG)的硬件实现,对于非敏感应用程序来说必须足够好。所以我想把它用在我的游戏里,而不是梅森·图斯特。
因此,为了查看使用该指令是否有任何性能提高,我比较了以下两种代码的时间:
// 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进行比较。因此,我采用了我的兔子实现(将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后门嵌入到每个人的软件密码学中的。此外,我们至少有一个比RDRAND更快的软件CSPRNG,最广泛使用的PRNG,Mersenne Twister,比RDRAND快得多。最后,我们有开源的可审计软件熵池,比如/dev/random和/dev/urandom,它们并不隐藏在像RDRAND这样的双重扰码层的背后。
那么,问题是人们应该使用RDRAND吗?它有什么合法用途吗?还是我们应该完全停止使用它?
发布于 2014-12-06 00:22:29
正如在另一个答案中指出的那样,RDRAND具有真正的随机性。特别是,它经常以128位硬件产生的随机性成功其内部CSPRNG,保证至少每511 * 128位重新分配一次。请参阅本文档的4.2.5节:
因此,在您的示例中,您使用了一个128位的种子来从rabbit_extract生成1,000万个随机抽签。在RDRAND版本中,您有相当于250万128位的绘图,这意味着CSPRING至少被重新加载了2,500,000/511 = 4,892乘以。
所以,在你的兔子例子中没有128位熵,而是至少有4,892*128 = 626,176位熵进入RDRAND示例。
在没有硬件支持的情况下,这比你在0.361秒内获得的熵要多得多。如果你在做很多真正的随机性很重要的事情,那可能很重要。一个例子是Shamir秘密共享大量数据--不确定是否还有其他数据。
总之,这不是为了速度,而是为了更高的安全性。当然,它是否落后的问题是令人不安的,但您可以始终将其与其他来源异或,而且至少不会对您造成伤害。
发布于 2014-11-06 14:30:03
RDRAND不仅仅是一个PRNG。这是一个白化TRNG是FIPS兼容。不同之处在于,您可以依赖RDRAND来包含从CPU直接检索到的相当多的实际熵。因此,RDRAND的主要用途是向OS/库/应用程序提供熵。
应用程序检索熵的唯一其他好方法通常是使用OS提供的熵源,如/dev/random或/dev/urandom (通常从/dev/random中提取熵)。然而,操作系统也需要在某个地方找到熵。通常,磁盘和网络访问时间的微小差异被用于此(+其他半随机输入)。这些设备并不总是存在,也不是作为熵源设计的;它们通常不是很好的源,也不是非常快的源。因此,在支持它的系统中,RDRAND经常被用作操作系统的密码安全随机数生成器的熵源。
关于速度,特别是在游戏中,使用(非安全) PRNG是完全有效的。如果你想要一个合理的随机种子,然后用RDRAND的结果播种它也许是个好主意,尽管从操作系统提供的RNG中播种它可能是一个更便携甚至更安全的选择(如果你不完全信任英特尔或美国)。
请注意,目前RDRAND是使用(AES) CTR_DRBG实现的,而不是为诸如兔子这样的速度而创建的(分析较少的)流密码,因此兔子更快一点也就不足为奇了。更重要的是,它还必须从CPU内的熵源中检索熵,然后才能运行。
发布于 2015-10-12 20:54:35
英特尔的RDRAND有什么合法的用途吗?
是。
以蒙特卡罗模拟为例。它不需要密码,所以不管它是否被美国国家安全局破坏了。
还是我们应该完全停止使用它?
我们不能回答。这是一个汇合用例、需求和个人偏好。
..。此外,我们至少有一个比RDRAND更快的软件CSPRNG,以及使用最广泛的最合适的PRNG.“
Mersenne在初始化后的时间内,由于从状态数组返回一个单词,所以在没有曲折的情况下,它的速度可能更快。但是我怀疑它的速度和RDRAND一样快,因为它是一条连续不断的河流。我知道RDRAND可以在连续流中实现基于总线宽度的理论极限。
根据英特尔的大卫约翰斯顿(谁设计的电路),这是类似于800+ MB/s。参见DJ在在常春藤桥上RDRAND指令的延迟和吞吐量是多少?的答案。
因此,我们有一种广泛的妄想,即RDRAND是用来将NSA后门嵌入到每个人的软件密码学中的。
偏执的人至少有两个选择。首先,他们可以放弃使用RDRAND和RDSEED。第二,它们可以使用RDRAND和RDSEED的输出为另一个生成器注入种子,然后使用第二个生成器的输出。我相信Linux内核采用了第二种方法。
https://stackoverflow.com/questions/26771329
复制相似问题