首先要声明的是,计算机不能生成绝对随机数,只能生成“伪随机数”。事实上,绝对随机数只是一个理想随机数。无论计算机如何发展,它都不会产生一系列绝对随机的数字。计算机只能产生相对随机数,即伪随机数。
伪随机数不是伪随机数。这里的“伪”是指正则,即计算机生成的伪随机数既有随机性又有正则性。怎么理解?生成的伪随机数有时服从某些规律,有时不服从任何规律;一些伪随机数遵守一定的规则;另一部分不遵循任何规则。比如“世界上没有两片形状完全相同的叶子”,指的是事物的特性,即随机性,但每棵树的叶子形状都是相似的,这就是事物的共性,即规律性。从这个角度来看,你可能会接受计算机只能生成伪随机数,而不能生成绝对随机数的事实。
首先,让我们理解真随机数和伪随机数的概念。
真随机数生成器:英语中的真随机数生成器,缩写为TRNGs,是通过不可预测的物理手段生成的随机数。
伪随机数发生器:英文是:伪随机数发生器,缩写为:PRNGs,由计算机使用一定的算法生成。
比较两种方法生成的随机数图片。
Random.org生成的随机位图(利用大气噪声生成随机数,由空中雷暴生成):
Windows下PHP的rand()函数生成的随机图片:
显然,后一种伪随机数发生器产生的图片具有这种明显的条纹。
使用php的rand random函数生成此图片的代码为:复制代码如下://需要打开gd库头(' content-type : image/png ');$im=imagecreatetruecolor(512,512)或die('无法初始化新的GD图像流');$white=imagecolorallocate($im,255,255,255);for($ y=0;512美元;$ y){ for($ x=0;$ x512$x ) {if (rand(0,1)==1){ imageset pixel($ im,$x,$y,$ white);} } } image png($ im);image destroy($ im);其实并不是所有的伪随机数发生器(PRNGs)都那么差,但是PHP在Windows下的rand()函数就是这样。如果在Linux下测试同样的代码,在图片中看不到明显的条纹。在Windows下,如果用mt_rand()函数代替rand()函数,效果会好很多。这是因为mt_rand()使用Mersenne Twister算法生成随机数。PHP文档还说,mt_rand()生成随机数的平均速度比libc提供的rand()快4倍。
此外,Linux内核(高于1.3.30)包括一个随机数生成器/dev/random,这对于许多安全目的来说已经足够了。
以下是对Linux随机数生成器原理的介绍:
Linux操作系统提供本质上随机的库数据(或者至少是随机性很强的组件)。这些数据通常来自设备驱动程序。例如,键盘驱动程序收集两个键之间的时间信息,然后将这种环境噪声填充到随机数生成器库中。
随机数据存储在熵池中(linux内核维护一个熵池,从设备驱动程序和其他来源收集环境噪声。理论上,熵池中的数据是完全随机的,可以生成真正的随机数序列。为了跟踪熵池中的数据,内核在将其添加到池中时会估计数据的随机性。这个过程叫做熵估计。熵估计值描述了池中包含的随机数的数量。值越大,池中数据的随机性越好。),每次有新数据进来,它都会“蠢蠢欲动”。这种搅动实际上是一种数学变换,有助于提高随机性。当数据被添加到熵池中时,系统估计获得了多少真实的随机位。
测量总随机性很重要。问题是,有些量看起来没有最初考虑的那么随机。例如,添加一个32位数字来表示自上次按下键盘后的秒数,实际上并不能提供新的32位随机信息,因为大多数键都非常接近。
从/dev/random读取字节后,熵池使用MD5算法进行加密哈希,哈希中的每个字节都转换为数字,然后返回。
如果熵池中没有可用的随机性位,/dev/random会等待,直到池中有足够的随机性,并且不会返回结果。这意味着如果使用/dev/random生成很多随机数,就会发现速度太慢,不够实用。我们经常看到/dev/random会生成几十个字节的数据,然后几秒钟都不会产生结果。
幸运的是,熵池的另一个接口可以绕过这个限制://dev/uran DOM。即使熵池中没有可用的随机性,这种替代设备也总是返回随机数。如果你拿掉了大多数,却没有给足够的时间去重新填充熵池,你就无法再从各种来源获得共享熵的好处;但是你仍然可以从熵池的MD5哈希中得到非常好的随机数!这种方法的问题是,如果有人破坏了MD5算法,并通过查看输出来了解哈希输入,您的数字将立即变得完全可预测。大多数专家一致认为,从计算的角度来看,这种分析是不可行的。然而,/dev/urandom仍然被认为比/dev/random“不太安全”(并且经常是有问题的)。
Windows下没有/dev/random可用,但是可以使用CAPICOM。微软capicom.dll公司提供的实用程序对象。
下面是一个使用PHP生成伪随机数比使用mt_rand()函数更好的示例代码:复制代码的代码如下:php//获取16字节字符串中的128个伪随机位
$ pr _ bits=
//Unix/Linux平台?$fp=@fopen('/dev/urandom ',' Rb ');if ($fp!==FALSE) {$pr_bits。=@fread($fp,16);@ fc lose($ FP);}
//MS-Windows平台?如果(@ class _ exists(' COM '){ try { $ CAPI _ Util=new COM(' CAPICOM。公用事业. 1 ');$ pr _ bits。=$CAPI_Util-GetRandom(16,0);
//如果我们请求二进制数据PHP munges它,那么我们//请求base64返回值。我们通过散列法挤出//冗余和无用的==CRLF.if($ pr _ bits){ $ pr _ bits=MD5($ pr _ bits,TRUE);} } catch(Exception $ ex){//echo“Exception :”。$ ex-Getmessage();}}
if (strlen($pr_bits) 16) {//采取措施警告系统所有者//伪随机发生器丢失}?
所以PHP需要调用外部元素来支持真随机数的生成!