PHP的伪随机数与真随机数详解


Posted in PHP onMay 27, 2015

首先需要声明的是,计算机不会产生绝对随机的随机数,计算机只能产生“伪随机数”。其实绝对随机的随机数只是一种理想的随机数,即使计算机怎样发展,它也不会产生一串绝对随机的随机数。计算机只能生成相对的随机数,即伪随机数。

伪随机数并不是假随机数,这里的“伪”是有规律的意思,就是计算机产生的伪随机数既是随机的又是有规律的。怎样理解呢?产生的伪随机数有时遵守一定的规律,有时不遵守任何规律;伪随机数有一部分遵守一定的规律;另一部分不遵守任何规律。比如“世上没有两片形状完全相同的树叶”,这正是点到了事物的特性,即随机性,但是每种树的叶子都有近似的形状,这正是事物的共性,即规律性。从这个角度讲,你大概就会接受这样的事实了:计算机只能产生伪随机数而不能产生绝对随机的随机数。

首先来了解一下真随机数和伪随机数的概念。

真随机数发生器:英文为:true random number generators ,简称为:TRNGs,是利用不可预知的物理方式来产生的随机数。

伪随机数发生器:英文为:pseudo-random number generators ,简称为:PRNGs,是计算机利用一定的算法来产生的。

对比一下两种办法产生的随机数的图片。

Random.org(利用大气噪音来生成随机数,而大气噪音是空气中的雷暴所产生的 )生成的随机位图:

PHP的伪随机数与真随机数详解

Windows下PHP的rand()函数产生的随机图片:

PHP的伪随机数与真随机数详解

很显然,后者伪随机数发生器产生的图片有这明显的条纹。

利用php的rand随机函数产生这张图片的代码为:

//需要开启gd库

header("Content-type: image/png");

$im = imagecreatetruecolor(512, 512)

or die("Cannot Initialize new GD image stream");

$white = imagecolorallocate($im, 255, 255, 255);

for ($y=0; $y<512; $y++) {

for ($x=0; $x<512; $x++) {

if (rand(0,1) === 1) {

imagesetpixel($im, $x, $y, $white);

}

}

}

imagepng($im);

imagedestroy($im);

实际上也并不是所有的伪随机数发生器(PRNGs)效果都这么差的,只是恰好在Windows下的PHP的rand()函数是这样。如果是在Linux下 测试相同的代码的话,所产生的图片也看不出明显的条纹。在Windows下如果用mt_rand()函数替代rand()函数的话效果也会好很多。这是由 于mt_rand()用了Mersenne Twister(马其塞旋转)算法来产生随机数。PHP的文档还说:mt_rand() 可以产生随机数值的平均速度比 libc 提供的 rand() 快四倍。

另外,Linux内核(1.3.30以上)包括了一个随机数发生器/dev/random ,对于很多安全目的是足够的。

下面是关于Linux的随机数发生器的原理介绍 :

Linux 操作系统提供本质上随机(或者至少具有强烈随机性的部件)的库数据。这些数据通常来自于设备驱动程序。例如,键盘驱动程序收集两个按键之间时间的信息,然后将这个环境噪声填入随机数发生器库。

随机数据存储在 熵池 ( linux内核维护了一个熵池用来收集来自设备驱动程序和其它来源的环境噪音。理论上,熵池中的数据是完全随机的,可以实现产生真随机数序列。为跟踪熵池中数据的随 机性,内核在将数据加入池的时候将估算数据的随机性,这个过程称作熵估算。熵估算值描述池中包含的随机数位数,其值越大表示池中数据的随机性越好。 ) 中,它在每次有新数据进入时进行“搅拌”。这种搅拌实际上是一种数学转换,帮助提高随机性。当数据添加到熵池中 后,系统估计获得了多少真正随机位。

测定随机性的总量是很重要的。问题是某些量往往比起先考虑时看上去的随机性小。例如,添加表示自从上次按键盘以来秒数的 32 位数实际上并没有提供新的 32 位随机信息,因为大多数按键都是很接近的。

从 /dev/random 中读取字节后,熵池就使用 MD5 算法进行密码散列,该散列中的各个字节被转换成数字,然后返回。

如果在熵池中没有可用的随机性位, /dev/random 在池中有足够的随机性之前等待,不返回结果。这意味着如果使用 /dev/random 来产生许多随机数,就会发现它太慢了,不够实用。我们经常看到 /dev/random 生成几十字节的数据,然后在许多秒内都不产生结果。

幸运的是有熵池的另一个接口可以绕过这个限制:/dev/urandom。即使熵池中没有随机性可用,这个替代设备也总是返回随机数。如果您取出许 多数而不给熵池足够的时间重新充满,就再也不能获得各种来源的合用熵的好处了;但您仍可以从熵池的 MD5 散列中获得非常好的随机数!这种方式的问题是,如果有任何人破解了 MD5 算法,并通过查看输出了解到有关散列输入的信息,那么您的数就会立刻变得完全可预料。大多数专家都认为这种分析从计算角度来讲是不可行的。然而,仍然认为 /dev/urandom 比 /dev/random 要“不安全一些”(并通常值得怀疑)。

Windows下没有/dev/random可用,但可以使用微软的“capicom.dll”所提供的CAPICOM.Utilities 对象。

以下是使用PHP时比用mt_rand()函数产生更好的伪随机数的一段例子代码:

<?php

// get 128 pseudorandom bits in a string of 16 bytes
$pr_bits = '';
// Unix/Linux platform?

$fp = @fopen('/dev/urandom','rb');

if ($fp !== FALSE) {

$pr_bits .= @fread($fp,16);

@fclose($fp);

}
// MS-Windows platform?

if (@class_exists('COM')) {

try {

$CAPI_Util = new COM('CAPICOM.Utilities.1');

$pr_bits .= $CAPI_Util->GetRandom(16,0);
// if we ask for binary data PHP munges it, so we

// request base64 return value. We squeeze out the

// redundancy and useless ==CRLF by hashing...

if ($pr_bits) { $pr_bits = md5($pr_bits,TRUE); }

} catch (Exception $ex) {

// echo 'Exception: ' . $ex->getMessage();

}

}
if (strlen($pr_bits) < 16) {

// do something to warn system owner that

// pseudorandom generator is missing

}

?>

所以PHP要产生真随机数 还是要调用外部元素来支持的!

PHP 相关文章推荐
PHP syntax error, unexpected $end 错误的一种原因及解决
Oct 25 PHP
php mysql_real_escape_string函数用法与实例教程
Sep 30 PHP
Drupal7连接多个数据库及常见问题解决
Mar 02 PHP
PHP中对于浮点型的数据需要用不同的方法解决
Mar 11 PHP
PHP的switch判断语句的“高级”用法详解
Oct 01 PHP
PHP读书笔记_运算符详解
Jul 01 PHP
PHP+Ajax异步带进度条上传文件实例
Nov 01 PHP
Yii2框架可逆加密简单实现方法
Aug 25 PHP
Laravel源码解析之路由的使用和示例详解
Sep 27 PHP
详解PHP变量传值赋值和引用赋值变量销毁
Mar 23 PHP
PHP模版引擎原理、定义与用法实例
Mar 29 PHP
laravel 解决Eloquent ORM的save方法无法插入数据的问题
Oct 21 PHP
php实现window平台的checkdnsrr函数
May 27 #PHP
PHP实现恶意DDOS攻击避免带宽占用问题方法
May 27 #PHP
PHP简单实现HTTP和HTTPS跨域共享session解决办法
May 27 #PHP
PHP实现即时输出、实时输出内容方法
May 27 #PHP
PHP ajax 异步执行不等待执行结果的处理方法
May 27 #PHP
PHP中preg_match函数正则匹配的字符串长度问题
May 27 #PHP
PHP中把有符号整型转换为无符号整型方法
May 27 #PHP
You might like
PHP使用mysqldump命令导出数据库
2015/04/14 PHP
PHP实现动态web服务器方法
2015/07/29 PHP
抽出www.templatemonster.com的鼠标悬停加载大图模板的代码
2007/07/11 Javascript
javascript globalStorage类代码
2009/06/04 Javascript
图标线性回归斜着移动到指定的位置
2013/08/16 Javascript
Jquery uploadify图片上传插件无法上传的解决方法
2013/12/16 Javascript
javascript 实现动态侧边栏实例详解
2016/11/11 Javascript
js原生之焦点图转换加定时器实例
2016/12/12 Javascript
jquery——九宫格大转盘抽奖实例
2017/01/16 Javascript
vue使用vue-cli快速创建工程
2017/07/28 Javascript
JavaScript表单即时验证 验证不成功不能提交
2017/08/31 Javascript
jQuery中extend函数简单用法示例
2017/10/11 jQuery
vue.js实现点击后动态添加class及删除同级class的实现代码
2018/04/04 Javascript
利用js将ajax获取到的后台数据动态加载至网页中的方法
2018/08/08 Javascript
Layer弹出层动态获取数据的方法
2018/08/20 Javascript
JS typeof fn === 'function' &amp;&amp; fn()详解
2020/08/22 Javascript
Python 查看文件的编码格式方法
2017/12/21 Python
100行Python代码实现自动抢火车票(附源码)
2018/01/11 Python
Python 实现交换矩阵的行示例
2019/06/26 Python
Python 用matplotlib画以时间日期为x轴的图像
2019/08/06 Python
python爬取王者荣耀全皮肤的简单实现代码
2020/01/31 Python
python基于opencv 实现图像时钟
2021/01/04 Python
纯CSS3实现自定义Tooltip边框涂鸦风格的教程
2014/11/05 HTML / CSS
html5视频播放_动力节点Java学院整理
2017/07/13 HTML / CSS
canvas实现图片马赛克的示例代码
2018/03/26 HTML / CSS
Jo Malone美国官网:祖玛珑香水
2017/03/27 全球购物
美国最佳选择产品网站:Best Choice Products
2019/05/27 全球购物
澳大利亚宠物食品和用品商店:PETstock
2020/01/02 全球购物
eharmony澳大利亚:网上约会服务
2020/02/29 全球购物
面向对象设计的原则是什么
2013/02/13 面试题
西北政法大学自主招生自荐信
2014/01/29 职场文书
一句话工作感言
2014/03/01 职场文书
2014乡镇党政班子四风问题思想汇报
2014/09/14 职场文书
2014年英语教学工作总结
2014/12/17 职场文书
文明上网主题班会
2015/08/14 职场文书
如何利用golang运用mysql数据库
2022/03/13 Golang