了解过 C 语言的应该都知道,在 C 标准库中的 rand 函数实际上是一种伪随机数生成算法。它使用“线性同余”算法进行一个迭代计算,这样计算的结果虽然分布上是满足随机分布的,但在得知具体算法及观察了当前数据之后,后续的随机数是可“预测”出来的。为了尽可能得到更“随机”的随机数,有很多种办法,而使用 CPU 内置的硬件随机数生成指令就是其中一种。
随机数的作用
如何在计算机中创造出真正的随机数一直是个大问题,小到猜谜抽奖游戏或摇骰子小程序,大到密码学、通信等领域都经常需要用到随机数。不少随机数用作加密通信中的安全密钥生成算法中以提高安全等级。如果计算机的随机数生成算法可被预测,那安全性就大大降低,所以如何生成尽可能真实的随机数非常重要。
硬件随机数
使用算法生成的随机数总是可以预测的,因为程序的执行结果是确定的。而硬件随机数通常是根据一些如“热噪声”、“宇宙射线”、“光电效应”等很玄学、根本无法有效观测及计算的现象进行采集的。以这些任何仪器都“测不准”的变量为计算元,就可以得到无法预测的随机数。
从Intel的Ivy Bridge架构开始,就提供了RdRand指令以使用CPU内部的热噪声、时序中断等生成的硬件随机数。
由于并不是所有的CPU都支持RdRand指令,所以在使用前要先进行检测:把eax寄存器置1并调用cpuid指令,如果支持RdRand的话,ecx寄存器的第30比特位会被置为1。
实现代码
先进行CPU检测,如果不支持RdRand指令,就继续使用线性同余算法: