摘要:本文主要分析以加密为目的的随机数生成问题。一个简例一个好的随机数生成系统能确保生成质量适合的随机数。此处,暂不深入讨论复杂的统计话题,将已知的行为与随机数生成器的结果进行比较,有助于质量评估。
本文主要分析以加密为目的的随机数生成问题。PHP 5 并未提供生成强加密随机数的简便机制,但是,PHP 7 引入了两个 CSPRNG 函数以解决该问题。系 OneAPM 工程师编译整理。
什么是 CSPRNG?引用维基百科的定义,密码安全的虚拟随机数生成器(Cryptographically Secure Pseudorandom Number Generator,CSPRNG)是带有特定属性使之在密码学中适用的虚拟随机数生成器(pseudo-random number generator,PRNG)。
CSPRNG 主要用于:
生成键(比如:生成复杂的键)
为新的用户账号生成随机密码
加密系统
保证高安全水准的一个重要因素便是高质量的随机数。
PHP 7 中的 CSPRNGPHP 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 官方技术博客。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/21278.html
摘要:本文分析了生成用于加密的随机数的相关问题。没有提供一种简单的机制来生成密码学上强壮的随机数,但是通过引入几个函数来解决了这个问题。呢缺省情况下,不提供强壮的随机数发生器。如果你想要使用可靠的随机数据源,如你在本文所见,建议尽快使用和 本文分析了生成用于加密的随机数的相关问题。 PHP 5没有提供一种简单的机制来生成密码学上强壮的随机数,但是PHP 7通过引入几个CSPRNG函数来解决了...
摘要:本文分析了生成用于加密的随机数的相关问题。没有提供一种简单的机制来生成密码学上强壮的随机数,但是通过引入几个函数来解决了这个问题。呢缺省情况下,不提供强壮的随机数发生器。如果你想要使用可靠的随机数据源,如你在本文所见,建议尽快使用和 本文分析了生成用于加密的随机数的相关问题。 PHP 5没有提供一种简单的机制来生成密码学上强壮的随机数,但是PHP 7通过引入几个CSPRNG函数来解决了...
摘要:使用微信企业号回调的坑最近在做企业号回调的接口,之前做过几个企业号的应用了,每次接入到都报各种各样的错误,算哥倒霉,该踩的不该踩的坑全踩了。 ThinkPHP 使用微信企业号回调的坑 最近在做企业号回调的接口,之前做过几个企业号的应用了,每次接入到Thinkphp都报各种各样的错误,算哥倒霉,该踩的不该踩的坑全踩了。 这次掉坑里差点就放弃了,开发过企业号的都知道,企业号回调会经过一个...
摘要:我们再来看国内一线公司内的一个实验吧数据训练营都在用的方法,详解测试的那些坑如上是不同的引导卡片样式的实验,最终结果样式比样式的提升。设指标数值隐变量列显变量列含方案变量。 作者|蚂蚁金服人工智能部产品经理 范磊 本文首发|微信公众号 友盟数据服务 (ID:umengcom),转载请注明出处 If you are not running experiments,you are prob...
摘要:先来说说关键字。什么时候用来修饰方法关键字大家都知道是用来修饰方法与属性的。一句话学会面向对象的方式来思考。充分发挥其性能优势,又能解决扩展性差的问题。这里不会进行与的比较。 你以为你知道了一切,只是你以为而已。知识的美妙就在于,一生的时光在它面前显得多么的短暂。 嗯嗯,扯远了,我今天只想说说:static 与 yield。 先来说说 static 关键字。本篇只讲静态方法的使用与后期...
阅读 2677·2021-11-16 11:53
阅读 2740·2021-07-26 23:38
阅读 2075·2019-08-30 15:55
阅读 1753·2019-08-30 13:21
阅读 3656·2019-08-29 17:26
阅读 3308·2019-08-29 13:20
阅读 876·2019-08-29 12:20
阅读 3192·2019-08-26 10:21