찾다
php教程php手册PHP中的随机性你觉得自己幸运吗?

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?

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
php怎么把负数转为正整数php怎么把负数转为正整数Apr 19, 2022 pm 08:59 PM

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

php怎么实现几秒后执行一个函数php怎么实现几秒后执行一个函数Apr 24, 2022 pm 01:12 PM

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

php怎么除以100保留两位小数php怎么除以100保留两位小数Apr 22, 2022 pm 06:23 PM

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

php怎么根据年月日判断是一年的第几天php怎么根据年月日判断是一年的第几天Apr 22, 2022 pm 05:02 PM

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

php字符串有没有下标php字符串有没有下标Apr 24, 2022 am 11:49 AM

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

php怎么替换nbsp空格符php怎么替换nbsp空格符Apr 24, 2022 pm 02:55 PM

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

php怎么判断有没有小数点php怎么判断有没有小数点Apr 20, 2022 pm 08:12 PM

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

php怎么读取字符串后几个字符php怎么读取字符串后几个字符Apr 22, 2022 pm 08:31 PM

在php中,可以使用substr()函数来读取字符串后几个字符,只需要将该函数的第二个参数设置为负值,第三个参数省略即可;语法为“substr(字符串,-n)”,表示读取从字符串结尾处向前数第n个字符开始,直到字符串结尾的全部字符。

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

Dreamweaver Mac版

Dreamweaver Mac版

시각적 웹 개발 도구

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

SublimeText3 영어 버전

SublimeText3 영어 버전

권장 사항: Win 버전, 코드 프롬프트 지원!

DVWA

DVWA

DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는