PHP中的随机性 你觉得自己幸运吗?


Posted in PHP onJanuary 22, 2016

本文分析了生成用于加密的随机数的相关问题。 PHP 5没有提供一种简单的机制来生成密码学上强壮的随机数,但是PHP 7通过引入几个CSPRNG函数来解决了这个问题。

PHP中的随机性 你觉得自己幸运吗?

一、什么是CSPRNG

引用维基百科,一个密码学上安全的伪随机数发生器(Cryptographically Secure Pseudorandom Number Generator 缩写CSPRNG)是一个伪随机数生成器(PRNG),其生成的伪随机数适用于密码学算法。

CSPRNG可能主要用于:

  • 密钥生成(例如,生成复杂的密钥)
  • 为新用户产生随机的密码
  • 加密系统

获得高级别安全性的一个关键方面就是高品质的随机性

二、PHP7 中的CSPRNG

PHP 7引入了两个新函数可以用来实现CSPRNG: random_bytes 和 random_int。

random_bytes 函数返回一个字符串,接受一个int型入参代表返回结果的字节数。

例子:

$bytes = random_bytes('10');
var_dump(bin2hex($bytes));
//possible ouput: string(20) "7dfab0af960d359388e6"

random_int 函数返回一个指定范围内的int型数字。

例子:

var_dump(random_int(1, 100));
//possible output: 27

三、后台运行环境

以上函数的随机性不同的取决于环境:

  • 在window上,CryptGenRandom()总是被使用。
  • 在其他平台,arc4random_buf()如果可用会被使用(在BSD系列或者具有libbsd的系统上成立)
  • 以上都不成立的话,一个linux系统调用getrandom(2)会被使用。
  • 如果还不行,/dev/urandom 会被作为最后一个可使用的工具
  • 如果以上都不行,系统会抛出错误

四、一个简单的测试

一个好的随机数生成系统保证合适的产生“质量”。为了检查这个质量, 通常要执行一连串的统计测试。不需要深入研究复杂的统计主题,比较一个已知的行为和数字生成器的结果可以帮助质量评价。

一个简单的测试是骰子游戏。假设掷1个骰子1次得到结果为6的概率是1/6,那么如果我同时掷3个骰子100次,得到的结果粗略如下:

0 个6 = 57.9 次
1 个6 = 34.7次
2 个6 = 6.9次
3 个6 = 0.5次
以下是是实现实现掷骰子1,000,000次的代码:

$times = 1000000;
$result = [];
for ($i=0; $i<$times; $i++){
  $dieRoll = array(6 => 0); //initializes just the six counting to zero
  $dieRoll[roll()] += 1; //first die
  $dieRoll[roll()] += 1; //second die
  $dieRoll[roll()] += 1; //third die
  $result[$dieRoll[6]] += 1; //counts the sixes
}
function roll(){
  return random_int(1,6);
}
var_dump($result);

用PHP7 的 random_int 和简单的 rand 函数可能得到如下结果

PHP中的随机性 你觉得自己幸运吗?

如果先看到rand 和 random_int 更好的比较我们可以应用一个公式把结果画在图上。公式是:(php结果-期待的结果)/期待结果的0.5次方。

结果图如下:

PHP中的随机性 你觉得自己幸运吗?

(接近0的值更好)

尽管3个6的结果表现不好,并且这个测试对实际应用来说太过简单我们仍可以看出 random_int 表现优于 rand.

进一步,我们的应用的安全级别由于不可预测性和随机数发生器的可重复行为而得到提升。

PHP5 呢

缺省情况下,PHP5 不提供强壮的随机数发生器。实际上,还是有选择的比如 openssl_random_pseudo_bytes(), mcrypt_create_iv() 或者直接使用fread()函数来使用 /dev/random 或 /dev/urandom 设备。也有一些包比如 RandomLib 或 libsodium.

如果你想要开始使用一个更好的随机数发生器并且同时准备好使用PHP7,你可以使用Paragon Initiative Enterprises random_compat 库。 random_compat 库允许你在 PHP 5.x project.使用 random_bytes() and random_int()

这个库可以通过Composer安装:

composer require paragonie/random_compat
require 'vendor/autoload.php';
$string = random_bytes(32);
var_dump(bin2hex($string));
// string(64) "8757a27ce421b3b9363b7825104f8bc8cf27c4c3036573e5f0d4a91ad2aaec6f"
$int = random_int(0,255);
var_dump($int);
// int(81)

random_compat 库和PHP7使用不同的顺序:

fread() /dev/urandom if available
mcrypt_create_iv($bytes, MCRYPT_CREATE_IV)
COM('CAPICOM.Utilities.1')->GetRandom()
openssl_random_pseudo_bytes()

这个库的一个简单应用用来产生密码:

$passwordChar = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$passwordLength = 8;
$max = strlen($passwordChar) - 1;
$password = '';
for ($i = 0; $i < $passwordLength; ++$i) {
  $password .= $passwordChar[random_int(0, $max)];
}
echo $password;
//possible output: 7rgG8GHu

总结

你总是应该使用一个密码学上安全的伪随机数生成器,random_compat 库提供了一种好的实现。

如果你想要使用可靠的随机数据源,如你在本文所见,建议尽快使用 random_int 和 random_bytes。

以上就是关于php随机性的相关内容,希望对大家的学习有所帮助。

PHP 相关文章推荐
简单采集了yahoo的一些数据
Feb 14 PHP
解决PHP在DOS命令行下却无法链接MySQL的技术笔记
Dec 29 PHP
ThinkPHP写第一个模块应用
Feb 20 PHP
PHP仿博客园 个人博客(2) 数据库增添改删
Jul 05 PHP
php生成缩略图填充白边(等比缩略图方案)
Dec 25 PHP
php实现可以设置中奖概率的抽奖程序代码分享
Jan 19 PHP
php 微信开发获取用户信息如何实现
Dec 13 PHP
PHP实现Huffman编码/解码的示例代码
Apr 20 PHP
PHP函数按引用传递参数及函数可选参数用法示例
Jun 04 PHP
Yii框架ACF(accessController)简单权限控制操作示例
Apr 26 PHP
php服务器的系统详解
Oct 12 PHP
PHP设计模式之装饰器(装饰者)模式(Decorator)入门与应用详解
Dec 13 PHP
PHP中的session安全吗?
Jan 22 #PHP
PHP下载远程图片并保存到本地方法总结
Jan 22 #PHP
PHP连接MYSQL数据库实例代码
Jan 20 #PHP
CodeIgniter配置之autoload.php自动加载用法分析
Jan 20 #PHP
Twig模板引擎用法入门教程
Jan 20 #PHP
CodeIgniter控制器之业务逻辑实例分析
Jan 20 #PHP
CodeIgniter自定义控制器MY_Controller用法分析
Jan 20 #PHP
You might like
PHP面向对象概念
2011/11/06 PHP
php数据结构与算法(PHP描述) 快速排序 quick sort
2012/06/21 PHP
使用php实现快钱支付功能(涉及到接口)
2013/07/01 PHP
php抽象类用法实例分析
2015/07/07 PHP
php写app接口并返回json数据的实例(分享)
2017/05/20 PHP
Swoole 5将移除自动添加Event::wait()特性详解
2019/07/10 PHP
jQuery EasyUI 开源插件套装 完全替代ExtJS
2010/03/24 Javascript
jQuery学习笔记之jQuery的事件
2010/12/22 Javascript
ajax更新数据后,jquery、jq失效问题
2011/03/16 Javascript
js jquery ajax的几种用法总结(及优缺点介绍)
2014/01/28 Javascript
Linux下使用jq友好的打印JSON技巧分享
2014/11/18 Javascript
JavaScript File API文件上传预览
2016/02/02 Javascript
详解如何构建Angular项目目录结构
2017/07/13 Javascript
Vue实例中生命周期created和mounted的区别详解
2017/08/25 Javascript
JS实现颜色的10进制转化成rgba格式的方法
2017/09/04 Javascript
信息滚动效果的实例讲解
2017/09/18 Javascript
webpack手动配置React开发环境的步骤
2018/07/02 Javascript
JavaScript判断对象和数组的两种方法
2019/05/31 Javascript
JS实现利用闭包判断Dom元素和滚动条的方向示例
2019/08/26 Javascript
jQuery实现移动端扭蛋机抽奖
2020/11/08 jQuery
[06:33]3.19 DOTA2发布会 海涛、冷冷、2009见证希望
2014/03/21 DOTA
使用Python的PEAK来适配协议的教程
2015/04/14 Python
Python爬取附近餐馆信息代码示例
2017/12/09 Python
更新pip3与pyttsx3文字语音转换的实现方法
2019/08/08 Python
Scrapy框架实现的登录网站操作示例
2020/02/06 Python
python各种excel写入方式的速度对比
2020/11/10 Python
HTML5如何实现元素拖拽
2016/03/11 HTML / CSS
关于HTML5+ API plusready的兼容问题
2020/11/20 HTML / CSS
生产总经理岗位职责
2013/12/19 职场文书
文明家庭先进事迹材
2014/01/27 职场文书
汉语言文学专业自荐信
2014/06/11 职场文书
医德医魂心得体会
2014/09/11 职场文书
监察建议书
2015/02/04 职场文书
毕业实习证明范本
2015/06/16 职场文书
用Python爬取各大高校并可视化帮弟弟选大学,弟弟直呼牛X
2021/06/11 Python
MySQL 开窗函数
2022/02/15 MySQL