lve*_*lla 10 random cryptography stream-cipher rdrand
今天我想:好吧,即使RDRAND对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);
}
Run Code Online (Sandbox Code Playgroud)
和
//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);
}
Run Code Online (Sandbox Code Playgroud)
通过运行这两个我得到:
$ time ./test
d230449a
real 0m0.361s
user 0m0.358s
sys 0m0.002s
$ time ./test2
bfc4e472
real 0m0.051s
user 0m0.050s
sys 0m0.002s
Run Code Online (Sandbox Code Playgroud)
因此,Mersenne Twister在我的CPU上比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]);
}
Run Code Online (Sandbox Code Playgroud)
令我惊讶的是,产生两倍于前两个的伪随机数据,我得到了比RDRAND更好的时间:
$ time ./test3
8ef9772277b70aba
real 0m0.344s
user 0m0.341s
sys 0m0.002s
Run Code Online (Sandbox Code Playgroud)
这三个都是在启用优化的情况下编译
因此,我们普遍存在一种偏执狂,即RDRAND将NSA后门嵌入到每个人的软件加密中.此外,我们至少有一个软件CSPRNG比RDRAND更快,使用最广泛的体面的PRNG,梅森难题,是多比RDRAND更快.最后,我们有开源可审计的软件熵池,比如/dev/random和/dev/urandom,并没有隐藏在双重加扰器层的后面,比如RDRAND.
所以,问题是:人们应该使用RDRAND吗?它有合法用途吗?或者我们应该完全停止使用它?
Jac*_*man 20
正如owlstead所指出的那样,RDRAND播种时具有真正的随机性.特别是,它经常使用128位硬件生成的随机性重新组合其内部CSPRNG,从而保证每511*128位至少重置一次.请参阅本文档的4.2.5节:
因此,在您的示例中,您使用单个128位种子从rabbit_extract生成1000万个随机抽取.在RDRAND版本中,您拥有相当于250万个128位绘图,这意味着CSPRING重新播种至少2,500,000/511 = 4,892次.
因此,在您的兔子示例中,不是128位熵,而是进入RDRAND示例中至少有4,892*128 = 626,176位熵.
这比在没有硬件支持的情况下在0.361秒内得到的熵要多得多.如果你正在做很多真正随机性很重要的事情,这可能很重要.一个例子是Shamir秘密共享大量数据 - 不确定是否还有其他数据.
总而言之 - 它不是速度,而是高安全性.当然,问题是它是否是后悔是令人不安的,但你总是可以与其他来源混淆,至少它不会伤害你.
RDRAND不只是PRNG。它是符合FIPS标准的白色TRNG。区别在于您可以依靠RDRAND包含直接从CPU检索的大量实际熵。因此,的主要用途RDRAND是向OS /库/应用程序提供熵。
应用程序检索熵的唯一其他好方法通常是使用OS提供的熵源,例如/dev/random或/dev/urandom(通常从中提取熵/dev/random)。但是,该OS还需要在某个地方找到熵。通常,为此使用磁盘和网络访问时间的微小差异(+其他半随机输入)。这些设备并不总是存在,也没有设计成熵的来源。它们通常不是很好的资源,也不是很快。因此,在支持它的系统上,RDRAND通常用作操作系统的安全加密随机数生成器的熵源。
关于速度,特别是对于游戏,使用(非安全)PRNG是完全有效的。如果您想拥有一个合理的随机种子,则以的结果作为种子RDRAND是一个好主意,尽管从操作系统提供的RNG进行种子注入可能是一种更可移植甚至更安全的选择(以防您不完全信任)英特尔或美国)。
请注意,当前RDRAND是使用(AES)CTR_DRBG来实现的,而不是使用诸如Rabbit之类的为速度而创建的(未经充分分析的)流密码来实现的,因此Rabbit速度更快也就不足为奇了。更重要的是,它还必须从CPU内的熵源检索熵,然后才能运行。
| 归档时间: |
|
| 查看次数: |
8633 次 |
| 最近记录: |