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 相关文章推荐
深入了解php4(1)--回到未来
Oct 09 PHP
PHP计数器的实现代码
Jun 08 PHP
php 判断是否是中文/英文/数字示例代码
Sep 30 PHP
phpmyadmin配置文件现在需要绝密的短密码(blowfish_secret)的2种解决方法
May 07 PHP
PHP文件读写操作相关函数总结
Nov 18 PHP
PHP遍历数组的三种方法及效率对比分析
Feb 12 PHP
php数组合并与拆分实例分析
Jun 12 PHP
WordPress中的shortcode短代码功能使用详解
May 17 PHP
curl 出现错误的调试方法(必看)
Feb 13 PHP
PHP实现表单提交数据的验证处理功能【防SQL注入和XSS攻击等】
Jul 21 PHP
PHP设计模式之单例模式原理与实现方法分析
Apr 25 PHP
PHP获取真实IP及IP模拟方法解析
Nov 24 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
ThinkPHP采用模块和操作分析
2011/04/18 PHP
PHP+Mysql+jQuery实现发布微博程序 php篇
2015/10/15 PHP
PHP simplexml_load_file()函数讲解
2019/02/03 PHP
php中目录操作opendir()、readdir()及scandir()用法示例
2019/06/08 PHP
PHP实现基本留言板功能原理与步骤详解
2020/03/26 PHP
JavaScript 使用技巧精萃(.net html
2009/04/25 Javascript
基于jquery &amp; json的省市区联动代码
2012/06/26 Javascript
nodejs命令行参数处理模块commander使用实例
2014/09/17 NodeJs
使用jQuery监听DOM元素大小变化
2016/02/24 Javascript
javascript对象的创建和访问
2016/03/08 Javascript
jQuery实现磁力图片跟随效果完整示例
2016/09/16 Javascript
JS实现获取来自百度,Google,soso,sogou关键词的方法
2016/12/21 Javascript
jQuery EasyUI的TreeGrid查询功能实现方法
2017/08/08 jQuery
ionic2屏幕适配实现适配手机、平板等设备的示例代码
2017/08/11 Javascript
原生js实现移动端触摸轮播的示例代码
2017/12/22 Javascript
Angular4 ElementRef的应用
2018/02/26 Javascript
在vue中使用公共过滤器filter的方法
2018/06/26 Javascript
Angular2之二级路由详解
2018/08/31 Javascript
Angular刷新当前页面的实现方法
2018/11/21 Javascript
Vue基本使用之对象提供的属性功能
2019/04/30 Javascript
layer弹出层自适应高度,垂直水平居中的实现
2019/09/16 Javascript
在vue中使用jsx语法的使用方法
2019/09/30 Javascript
JavaScript观察者模式原理与用法实例详解
2020/03/10 Javascript
JS字符串和数组如何实现相互转化
2020/07/02 Javascript
vue中利用three.js实现全景图的完整示例
2020/12/07 Vue.js
windows上安装Anaconda和python的教程详解
2017/03/28 Python
python+requests+unittest API接口测试实例(详解)
2017/06/10 Python
python实现QQ空间自动点赞功能
2019/04/09 Python
data:image data url 文件转为Blob上传后端的方法
2019/07/16 HTML / CSS
BIBLOO捷克:购买女装、男装、童装、鞋和配件
2017/01/27 全球购物
应届护士推荐信
2013/11/16 职场文书
《将心比心》教学反思
2014/04/08 职场文书
2014年后备干部工作总结
2014/12/08 职场文书
2014年财务个人工作总结
2014/12/08 职场文书
劳动保障个人工作总结
2015/03/04 职场文书
Win11跳过联网界面创建本地管理账户的3种方法
2022/04/20 数码科技