随机数产生器(random number generator)

随机数产生器

随机数产生器一般分为真正的随机和伪随机(pseudorandom number generator (PRNG))。真正的随机则是不可预测的;伪随机则依靠随机数种子和随机算法,是可能被预测的。很多东西被黑客攻破与此有关。比如非常著名的美国所谓的标准随机数产生器的后门事件,简单来讲,就是“美国所谓的标准随机数产生器里面居然存在后门,通过某个常数,可以预测未来的随机数,从而攻破任何用此随机数产生器的加密设备。

Dual_EC_DRBG是美国国家标准技术研究院所制定的4个随机数标准算法之一。该算法使用了一个常数Q,如果该常数经过特殊选择,并且用来选择常数所使用的数据被保存,那么在知道该算法生成随机数前32个字节的情况下,可以预测未来所有生成的随机数。因此,如果该算法被植入后门,攻击者就可获知利用Dual_EC_DRBG算法生成的加解密密钥,从而使得保护的秘密泄露。2014年4月21日,美国国家标准技术研究院所宣布从随机数标准算法中删除Dual_EC_DRBG。

只依靠计算机程序,不依赖硬件和外部噪音能否产生真正的随机?
个人分析:
不可能。原因如下:种子是可选择的,产生序列的算法代码也是固定的,那么这个序列则是可以预测的,即使引入“时间”这种动态的变量,也是一个可以获取和预测的变量,那么最终的序列仍然可能被预测。这就是为何很多利用伪随机数进行加密而比较容易被破解的原因之一。综合而言,采用固定变量产生的信息是可能被预测的,这是我个人的理解。 当然,不能用我们大部分人攻不破而证明是“不可被预测”,也许黑客可以。D:)

我们举个例子:

    public static void main(String args[])
    {
        Random rnd = new Random(10);
        for(int i=0;i<10;i++)
            System.out.println(rnd.nextInt());
    }
   运行两次的结果:
-1157793070
1913984760
1107254586
1773446580
254270492
-1408064384
1048475594
1581279777
-778209333
1532292428



-1157793070
1913984760
1107254586
1773446580
254270492
-1408064384
1048475594
1581279777
-778209333
1532292428

很容易看出,java的Random类的nextInt方法,只要固定了seed,连续两次的运行序列是一样的,这显然不能算作真正的随机,采用这种方法产生的序列,几乎100%可预测,而且极其容易。如果稍微变化一下seedseed稍微设置的复杂一些,这种序列的变化只是变得复杂,但仍然是可能被预测的。

当然,大部分程序和语言中的随机数(比如Java, C 中的,MATLAB 中的),是伪随机。是由可确定的函数(常用线性同余),

Xn+1=(aXn+c)  mod  m

通过一个种子(常用时钟),产生的伪随机数。这意味着:如果知道了种子,或者已经产生的随机数,都可能获得接下来随机数序列的信息(可预测性)。
那么能否产生真的随机呢?
可以。软件的方法有缺陷,都是固化的变量和信息(至少是可知的),引入系统外的变量(把软件,代码,算法想象成一个封闭的系统)才可能产生真的随机性。
一个典型的例子就是 UNIX 内核中的随机数发生器(/dev/random),它在理论上能产生真随机。即这个随机数的生成,独立于生成函数,这时我们说这个产生器是非确定的。具体来讲,UNIX 维护了一个熵池,不断收集非确定性的设备事件,即机器运行环境中产生的硬件噪音来作为种子。比如说:时钟,IO 请求的响应时间,特定硬件中断的时间间隔,键盘敲击速度,鼠标位置变化,甚至周围的电磁波等等……直观地说,你每按一次键盘,动一下鼠标,邻居家 wifi 信号强度变化,磁盘写入速度,等等信号,都可能被用来生成随机数。
我们来分析一下linux里的c代码简略看一下:

==============================
The current exported interfaces for gathering environmental noise from the devices are:

* void add_device_randomness(const void *buf, unsigned int size);

* void add_input_randomness(unsigned int type, unsigned int           code, unsigned int value);

* void add_interrupt_randomness(int irq, int irq_flags);

* void add_disk_randomness(struct gendisk *disk);

add_device_randomness() is for adding data to the random pool that is likely to differ between two devices (or possibly even per boot). This would be things like ***MAC*** addresses or serial numbers, or the read-out of the RTC. This does *not* add any actual entropy to the pool, but it initializes the pool to different values for devices that might otherwise be identical and have very little entropy available to them (particularly common in the embedded world).

add_input_randomness() uses the input layer interrupt timing, as well as the event type information from the hardware.

add_interrupt_randomness() uses the interrupt timing as random inputs to the entropy pool. Using the cycle counters and the irq source as inputs, it feeds the randomness roughly once a second.

add_disk_randomness() uses what amounts to the seek time of block layer request events, on a per-disk_devt basis, as input to the entropy pool. Note that high-speed solid state drives with very low seek times do not make for good sources of entropy, as their seek times are usually fairly consistent. All of these routines try to estimate how many bits of randomness a particular randomness source.  They do this by keeping track of the first and second order deltas of the event timings.

个人以为,通过依赖于硬件的变量产生的信息在结合优秀的软件算法,理论上是可以产生真随机的。

伪随机

当然,我们工程中,大部分用的都是伪随机,其实也没必要用真随机。比如:中奖的随机数产生器,没必要非要追求真随机。本来就是”模拟“。
另外,随机数发生器对局部搜索的影响是存在的,可以参考各种论文。比如:

雷桂媛. 关于蒙特卡罗及拟蒙特卡罗方法的若干研究[D]. 浙江: 浙江大学, 2003.

什么是好的伪随机数发生器

主要是看:随机分布的优劣
主要看四个方面:
1. 相同序列的概率非常低。
2. 符合统计学的平均性,比如所有数字出现概率应该相同,卡方检验应该能通过,超长游程长度概略应该非常小,自相关应该只有一个尖峰,任何长度的同一数字之后别的数字出现概率应该仍然是相等的等等。
3. 不应该能够从一段序列猜测出随机数发生器的工作状态或者下一个随机数。
4. 不应该从随机数发生器的状态能猜测出随机数发生器以前的工作状态。

参考:

  1. Functionality Classes and Evaluation Methodology
    for Deterministic Random Number Generators.
  2. Pseudorandom_number_generator.

我们一般用的随机数发生器至少要符合1和2,而用于加密等应用的随机数发生器应该符合3和4。

引用文献

https://en.wikipedia.org/wiki/List_of_random_number_generators
https://www.zhihu.com/question/20423025/answer/15097735
https://en.wikipedia.org/wiki/Mersenne_Twister

你可能感兴趣的:(算法,基础知识)