PHP 中的随机数——你觉得可靠么?
2015-12-22 15:27
323 查看
本文主要分析以加密为目的的随机数生成问题。PHP 5 并未提供生成强加密随机数的简便机制,但是,PHP 7 引入了两个 CSPRNG 函数以解决该问题。系 OneAPM 工程师编译整理。
CSPRNG 主要用于:
生成键(比如:生成复杂的键)
为新的用户账号生成随机密码
加密系统
保证高安全水准的一个重要因素便是高质量的随机数。
例如:
举例:
在 Windows 系统,会使用
在其他平台,会优先使用
若以上两点均不符合,会使用 Linux getrandom(2) 系统调用。
若以上来源均不符合,会抛出
一个简单的测试方法是掷骰游戏。假设投掷一次,投出6的概率是1/6。如果同时投掷三个骰子,投100次,投得零次、一次、两次及三次6的次数大概是:
0 次6 = 57.9 次
1 次6 = 34.7 次
2 次6 = 6.9 次
3 次6 = 0.5 次
以下是骰子投掷100万次的代码:
用 PHP 7 的
更直观地查看
得到的结果如下:
(结果越接近零越好)
即便三个6的组合表现一般,且该测试与真实应用相比太过简单,我们也能清楚地看到
如果你想用一个比较好的随机数生成器,同时能与 PHP 7 兼容,你可以使用 Paragon Initiative 公司的
该库可以使用 Composer 进行安装:
该
如果可用,先使用 fread() /dev/urandom
mcrypt_create_iv($bytes, MCRYPT_CREATE_IV)
COM('CAPICOM.Utilities.1')->GetRandom()
openssl_random_pseudo_bytes()
想了解为何采用这一优先序列,可以阅读本文档。
使用该库生成密码的简单案例如下:
如果你想使用可靠的随机数来源,正如前文所述,尽快开始使用
**原文地址:http://www.sitepoint.com/randomness-php-feel-lucky/**
OneAPM for PHP 能够深入到所有 PHP 应用内部完成应用性能管理 能够深入到所有 PHP 应用内部完成应用性能管理和监控,包括代码级别性能问题的可见性、性能瓶颈的快速识别与追溯、真实用户体验监控、服务器监控和端到端的应用性能管理。想阅读更多技术文章,请访问 OneAPM 官方技术博客。
什么是 CSPRNG?
引用维基百科的定义,密码安全的虚拟随机数生成器(Cryptographically Secure Pseudorandom Number Generator,CSPRNG)是带有特定属性使之在密码学中适用的虚拟随机数生成器(pseudo-random number generator,PRNG)。CSPRNG 主要用于:
生成键(比如:生成复杂的键)
为新的用户账号生成随机密码
加密系统
保证高安全水准的一个重要因素便是高质量的随机数。
PHP 7 中的 CSPRNG
PHP 7 为 CSPRNG 引入了两种新函数:random_bytes与
random_int。
random_bytes函数返回
string类型,并接受一个
int类型为参数,该参数规定了所返回字符串的字节长度。
例如:
$bytes = random_bytes('10'); var_dump(bin2hex($bytes)); //possible ouput: string(20) "7dfab0af960d359388e6"
random_int函数返回给定范围内的整型数字。
举例:
var_dump(random_int(1, 100)); //possible output: 27
幕后解密
以上函数的随机数来源因环境不同而有所差异:在 Windows 系统,会使用
CryptGenRandom()函数。
在其他平台,会优先使用
arc4random_buf()函数(限 BSD 衍生系统或带 libbsd 的系统)。
若以上两点均不符合,会使用 Linux getrandom(2) 系统调用。
若以上来源均不符合,会抛出
Error。
一个简例
一个好的随机数生成系统能确保生成质量适合的随机数。为了检验质量,需要运行一系列的统计试验。此处,暂不深入讨论复杂的统计话题,将已知的行为与随机数生成器的结果进行比较,有助于质量评估。一个简单的测试方法是掷骰游戏。假设投掷一次,投出6的概率是1/6。如果同时投掷三个骰子,投100次,投得零次、一次、两次及三次6的次数大概是:
0 次6 = 57.9 次
1 次6 = 34.7 次
2 次6 = 6.9 次
3 次6 = 0.5 次
以下是骰子投掷100万次的代码:
$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);
用 PHP 7 的
random_int与简单的
rand函数测试上面的代码,可能会得到:
Sixes | expected | random_int | rand |
---|---|---|---|
0 | 579000 | 579430 | 578179 |
1 | 347000 | 346927 | 347620 |
2 | 69000 | 68985 | 69586 |
3 | 5000 | 4658 | 4615 |
rand与
random_int的差别,可以运用方程式放大两组结果的差异,并绘制成图表:
php result - expected result / sqrt(expected)
得到的结果如下:
(结果越接近零越好)
即便三个6的组合表现一般,且该测试与真实应用相比太过简单,我们也能清楚地看到
random_int的表现优于
rand。况且,随机数生成器的可预见行为、重复行为越少,应用的安全程度就更高。
PHP 5 又如何呢?
默认情况下,PHP 5 并未提供任何强虚拟随机数生成器。而实际使用中,可以使用openssl_random_pseudo_bytes()、
mcrypt_create_iv()方法,或直接结合使用
/dev/random或
/dev/urandom与
fread()方法。此外,还有包 RandomLib 或 libsodium。
如果你想用一个比较好的随机数生成器,同时能与 PHP 7 兼容,你可以使用 Paragon Initiative 公司的
random_compat库。该库允许在 PHP 5.x 项目中使用
random_bytes()与
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库使用了与 PHP 7 中不同的优先序列:
如果可用,先使用 fread() /dev/urandom
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吧!
**原文地址:http://www.sitepoint.com/randomness-php-feel-lucky/**
OneAPM for PHP 能够深入到所有 PHP 应用内部完成应用性能管理 能够深入到所有 PHP 应用内部完成应用性能管理和监控,包括代码级别性能问题的可见性、性能瓶颈的快速识别与追溯、真实用户体验监控、服务器监控和端到端的应用性能管理。想阅读更多技术文章,请访问 OneAPM 官方技术博客。
相关文章推荐
- php 下 POST方法提交参数丢失问题
- PHP 中的随机数——你觉得可靠么?
- PHP--时区配置
- 配置eAccelerator和XCache扩展来加速PHP程序的执行
- Thinkphp编辑器扩展类kindeditor用法
- PHP中使用RSA加密总结
- PHP socket类
- php获取字符串拼音和拼音首字母
- 学PHP避免即将到来的就业危机
- PHP学习的一种习惯
- PHPCMS 实现上一篇、下一篇
- Yii框架操作数据库的几种方式与mysql_escape_string
- 在windows下ftp服务器上传文件错误
- 如果ftp服务器使用windows下IIS创建,通过资源管理器登陆ftp服务器,输入正确的用户名和密码,点击登陆按钮没有反应
- php验证是否为非零整数(正整数、负整数)
- 在PHPstorm编辑器中配置git环境
- php 连接主从数据库
- Laravel 5.1 + OAuth2 PasswordGrant(密码授权模式)
- 20个基于PHP的开源内容管理系统推荐
- php session是否存在被破译的可能?