8

使用x86硬件随机数指令RdRand生成随机数

 2 years ago
source link: https://blog.sbw.so/u/using-x86-hardware-random-number-generator.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

使用x86硬件随机数指令RdRand生成随机数

来源: sbw Blog | 浏览: 3033 | 评论: 0 发表时间: 2019-04-13

了解过 C 语言的应该都知道,在 C 标准库中的 rand 函数实际上是一种伪随机数生成算法。它使用“线性同余”算法进行一个迭代计算,这样计算的结果虽然分布上是满足随机分布的,但在得知具体算法及观察了当前数据之后,后续的随机数是可“预测”出来的。为了尽可能得到更“随机”的随机数,有很多种办法,而使用 CPU 内置的硬件随机数生成指令就是其中一种。

随机数的作用

如何在计算机中创造出真正的随机数一直是个大问题,小到猜谜抽奖游戏或摇骰子小程序,大到密码学、通信等领域都经常需要用到随机数。不少随机数用作加密通信中的安全密钥生成算法中以提高安全等级。如果计算机的随机数生成算法可被预测,那安全性就大大降低,所以如何生成尽可能真实的随机数非常重要。

硬件随机数

使用算法生成的随机数总是可以预测的,因为程序的执行结果是确定的。而硬件随机数通常是根据一些如“热噪声”、“宇宙射线”、“光电效应”等很玄学、根本无法有效观测及计算的现象进行采集的。以这些任何仪器都“测不准”的变量为计算元,就可以得到无法预测的随机数。

从Intel的Ivy Bridge架构开始,就提供了RdRand指令以使用CPU内部的热噪声、时序中断等生成的硬件随机数。

由于并不是所有的CPU都支持RdRand指令,所以在使用前要先进行检测:把eax寄存器置1并调用cpuid指令,如果支持RdRand的话,ecx寄存器的第30比特位会被置为1。

先进行CPU检测,如果不支持RdRand指令,就继续使用线性同余算法:

static unsigned long int next = 1;
struct RandResult
{
bool success;
int rand;
};
RandResult rand_using_x86_rdrand()
{
const int retry_times = 10;
int32_t success = 1;
int32_t random = 0;
asm volatile ("mov $1, %%eax \n"
"cpuid \n"
"bt $30, %%ecx \n"
"jnc _fail \n"
""
"mov %2, %%ecx \n"
"retry: \n"
"rdrand %%eax \n"
"jc _end \n"
"loop retry \n"
""
"_fail: \n"
"mov $0, %0 \n"
"_end: \n"
"mov %%eax, %1 \n"
: "=al"(success), "=al"(random)
: "m"(retry_times)
: "%eax", "%ecx");
return { success, random };
}
int rand()
{
const auto r = rand_using_x86_rdrand();
if (r.success)
return r.rand;
next = next * 1103515245 + 12345;
return (unsigned int)(next / 65536) % 32768;
}
void srand(unsigned int seed)
{
next = seed;
}

引用本文请以超链接形式保留本文地址

没有人评论过此文,还不快抢个沙发!

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK