PHP中的随机性——你觉得自己幸运吗?
本文分析了生成用于加密的随机数的相关问题。 PHP 5没有提供一种简单的机制来生成密码学上强壮的随机数,但是PHP 7通过引入几个CSPRNG函数来解决了这个问题。
什么是CSPRNG
引用维基百科,一个密码学上安全的伪随机数发生器Cryptographically Secure Pseudorandom Number Generator 缩写CSPRNG)是一个伪随机数生成器PRNG),其生成的伪随机数适用于密码学算法。
CSPRNG可能主要用于:
-
密钥生成例如,生成复杂的密钥)
-
为新用户产生随机的密码
-
加密系统
获得高级别安全性的一个关键方面就是高品质的随机性
PHP7 中的CSPRNG
PHP 7引入了两个新函数可以用来实现CSPRNG: random_bytes 和 random_int。
random_bytes 函数返回一个字符串,接受一个int型入参代表返回结果的字节数。
例子:
<ol class="dp-j"><li class="alt"><span><span>$bytes = random_bytes(</span><span class="string">'10'</span><span>); </span></span></li><li><span>var_dump(bin2hex($bytes)); </span></li><li class="alt"><span><span class="comment">//possible ouput: string(20) "7dfab0af960d359388e6"</span><span> </span></span></li></ol>
random_int 函数返回一个指定范围内的int型数字。
例子:
<ol class="dp-j"><li class="alt"><span><span>var_dump(random_int(</span><span class="number">1</span><span>, </span><span class="number">100</span><span>)); </span></span></li><li><span><span class="comment">//possible output: 27</span><span> </span></span></li></ol>
后台运行环境
以上函数的随机性不同的取决于环境:
-
在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次的代码:
<ol class="dp-j"><li class="alt"><span><span>$times = </span><span class="number">1000000</span><span>; </span></span></li><li><span>$result = []; </span></li><li class="alt"><span><span class="keyword">for</span><span> ($i=</span><span class="number">0</span><span>; $i<$times; $i++){ </span></span></li><li><span> $dieRoll = array(<span class="number">6</span><span> => </span><span class="number">0</span><span>); </span><span class="comment">//initializes just the six counting to zero</span><span> </span></span></li><li class="alt"><span> $dieRoll[roll()] += <span class="number">1</span><span>; </span><span class="comment">//first die</span><span> </span></span></li><li><span> $dieRoll[roll()] += <span class="number">1</span><span>; </span><span class="comment">//second die</span><span> </span></span></li><li class="alt"><span> $dieRoll[roll()] += <span class="number">1</span><span>; </span><span class="comment">//third die</span><span> </span></span></li><li><span> $result[$dieRoll[<span class="number">6</span><span>]] += </span><span class="number">1</span><span>; </span><span class="comment">//counts the sixes</span><span> </span></span></li><li class="alt"><span>} </span></li><li><span>function roll(){ </span></li><li class="alt"><span> <span class="keyword">return</span><span> random_int(</span><span class="number">1</span><span>,</span><span class="number">6</span><span>); </span></span></li><li><span>} </span></li><li class="alt"><span>var_dump($result); </span></li></ol>
用PHP7 的 random_int 和简单的 rand 函数可能得到如下结果
Sixes |
expected |
random_int |
0 |
579000 |
579430 |
1 |
347000 |
346927 |
2 |
69000 |
68985 |
3 |
5000 |
4658 |
如果先看到rand 和 random_int 更好的比较我们可以应用一个公式把结果画在图上。公式是:(php结果-期待的结果)/期待结果的0.5次方。
结果图如下:
接近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安装:
<ol class="dp-j"><li class="alt"><span><span>composer require paragonie/random_compat </span></span></li><li><span> </span></li><li class="alt"><span>require <span class="string">'vendor/autoload.php'</span><span>; </span></span></li><li><span>$string = random_bytes(<span class="number">32</span><span>); </span></span></li><li class="alt"><span>var_dump(bin2hex($string)); </span></li><li><span><span class="comment">// string(64) "8757a27ce421b3b9363b7825104f8bc8cf27c4c3036573e5f0d4a91ad2aaec6f"</span><span> </span></span></li><li class="alt"><span>$<span class="keyword">int</span><span> = random_int(</span><span class="number">0</span><span>,</span><span class="number">255</span><span>); </span></span></li><li><span>var_dump($<span class="keyword">int</span><span>); </span></span></li><li class="alt"><span><span class="comment">// int(81)</span><span> </span></span></li></ol>
random_compat 库和PHP7使用不同的顺序:
<ol class="dp-j"><li class="alt"><span><span>fread() /dev/urandom </span><span class="keyword">if</span><span> available </span></span></li><li><span>mcrypt_create_iv($bytes, MCRYPT_CREATE_IV) </span></li><li class="alt"><span>COM(<span class="string">'CAPICOM.Utilities.1'</span><span>)->GetRandom() </span></span></li><li><span>openssl_random_pseudo_bytes() </span></li></ol>
想知道为什么是这个顺序建议阅读 documentation.
这个库的一个简单应用用来产生密码:
<ol class="dp-j"><li class="alt"><span><span>$passwordChar = </span><span class="string">'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'</span><span>; </span></span></li><li><span>$passwordLength = <span class="number">8</span><span>; </span></span></li><li class="alt"><span>$max = strlen($passwordChar) - <span class="number">1</span><span>; </span></span></li><li><span>$password = <span class="string">''</span><span>; </span></span></li><li class="alt"><span><span class="keyword">for</span><span> ($i = </span><span class="number">0</span><span>; $i < $passwordLength; ++$i) { </span></span></li><li><span> $password .= $passwordChar[random_int(<span class="number">0</span><span>, $max)]; </span></span></li><li class="alt"><span>} </span></li><li><span>echo $password; </span></li><li class="alt"><span><span class="comment">//possible output: 7rgG8GHu</span><span> </span></span></li></ol>
总结
你总是应该使用一个密码学上安全的伪随机数生成器,random_compat 库提供了一种好的实现。
如果你想要使用可靠的随机数据源,如你在本文所见,建议尽快使用 random_int 和 random_bytes.
译文链接:http://www.codeceo.com/article/php-random.html
英文原文:Randomness in PHP – Do You Feel Lucky?

php把负数转为正整数的方法:1、使用abs()函数将负数转为正数,使用intval()函数对正数取整,转为正整数,语法“intval(abs($number))”;2、利用“~”位运算符将负数取反加一,语法“~$number + 1”。

实现方法:1、使用“sleep(延迟秒数)”语句,可延迟执行函数若干秒;2、使用“time_nanosleep(延迟秒数,延迟纳秒数)”语句,可延迟执行函数若干秒和纳秒;3、使用“time_sleep_until(time()+7)”语句。

php除以100保留两位小数的方法:1、利用“/”运算符进行除法运算,语法“数值 / 100”;2、使用“number_format(除法结果, 2)”或“sprintf("%.2f",除法结果)”语句进行四舍五入的处理值,并保留两位小数。

判断方法:1、使用“strtotime("年-月-日")”语句将给定的年月日转换为时间戳格式;2、用“date("z",时间戳)+1”语句计算指定时间戳是一年的第几天。date()返回的天数是从0开始计算的,因此真实天数需要在此基础上加1。

方法:1、用“str_replace(" ","其他字符",$str)”语句,可将nbsp符替换为其他字符;2、用“preg_replace("/(\s|\ \;||\xc2\xa0)/","其他字符",$str)”语句。

php判断有没有小数点的方法:1、使用“strpos(数字字符串,'.')”语法,如果返回小数点在字符串中第一次出现的位置,则有小数点;2、使用“strrpos(数字字符串,'.')”语句,如果返回小数点在字符串中最后一次出现的位置,则有。

php字符串有下标。在PHP中,下标不仅可以应用于数组和对象,还可应用于字符串,利用字符串的下标和中括号“[]”可以访问指定索引位置的字符,并对该字符进行读写,语法“字符串名[下标值]”;字符串的下标值(索引值)只能是整数类型,起始值为0。

在PHP中,可以利用implode()函数的第一个参数来设置没有分隔符,该函数的第一个参数用于规定数组元素之间放置的内容,默认是空字符串,也可将第一个参数设置为空,语法为“implode(数组)”或者“implode("",数组)”。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

Atom编辑器mac版下载
最流行的的开源编辑器

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境