php 获取a-z中随机
This article analyzes problems related to random number generation used for cryptography purposes. PHP 5 does not provide an easy mechanism for generating cryptographically strong random numbers, while PHP 7 solves this by introducing a couple of CSPRNG functions.
本文分析了与用于加密目的的随机数生成有关的问题。 PHP 5没有提供一种简单的机制来生成具有密码强度的随机数,而PHP 7通过引入几个CSPRNG函数来解决此问题。
什么是CSPRNG? (What Is a CSPRNG?)
Quoting Wikipedia, a Cryptographically Secure Pseudorandom Number Generator (CSPRNG) is a pseudo-random number generator (PRNG) with properties that make it suitable for use in cryptography.
引用维基百科 ,加密安全的伪随机数生成器(CSPRNG)是一种伪随机数生成器(PRNG),其属性使其适合在密码学中使用。
A CSPRNG could be mainly useful for:
CSPRNG主要可用于:
- Key generation (e.g. generation of complicated keys) 密钥生成(例如,复杂密钥的生成)
- Creating random passwords for new user accounts 为新用户帐户创建随机密码
- Encryption systems 加密系统
A central aspect to keeping a high security level is the high quality of randomness.
保持高安全级别的一个主要方面是高质量的随机性。
PHP 7中的CSPRNG (CSPRNG in PHP 7)
PHP 7 introduces two new functions that can be used for CSPRNG: random_bytes
and random_int
.
PHP 7引入了两个可用于CSPRNG的新函数: random_bytes
和random_int
。
The random_bytes
function returns a string
and accepts as input an int
representing the length in bytes to be returned.
random_bytes
函数返回一个string
并接受一个表示要返回的字节长度的int
作为输入。
Example:
例:
$bytes = random_bytes('10');
var_dump(bin2hex($bytes));
//possible ouput: string(20) "7dfab0af960d359388e6"
The random_int
function returns an integer number within the given range. Example:
random_int
函数返回给定范围内的整数。 例:
var_dump(random_int(1, 100));
//possible output: 27
幕后花絮 (Behind the Scenes)
The sources of randomness of the above functions are different depending on the environment:
上述功能的随机性源因环境而异:
On Windows,
CryptGenRandom()
will always be used.在Windows上,将始终使用
CryptGenRandom()
。On other platforms,
arc4random_buf()
will be used if it is available (true on BSD derivatives or systems with libbsd).在其他平台上,如果可用,将使用
arc4random_buf()
(在BSD派生类或具有libbsd的系统上为true)。Failing the above, a Linux getrandom(2) syscall will be used.
如果失败,将使用Linux getrandom(2) syscall。
- If all else fails /dev/urandom will be used as the final fallback. 如果其他所有方法都失败,则将/ dev / urandom用作最终的后备。
If none of the above sources are available, then an
Error
will be thrown.如果以上来源均不可用,则将引发
Error
。
一个简单的测试 (A Simple Test)
A good random number generation system assures the right “quality” of generations. To check this quality, a battery of statistical tests is often performed. Without delving into complex statistical topics, comparing a known behavior with the result of a number generator can help in a quality evaluation.
一个好的随机数生成系统可以确保正确的生成“质量”。 为了检查该质量,经常执行一系列统计测试。 在不研究复杂的统计主题的情况下,将已知行为与数字生成器的结果进行比较可以帮助进行质量评估。
One easy test is the dice game. Assuming the odds of rolling a six with one die are one in six, if I roll three dice at the same time 100 times, the expected values for 0, 1, 2, and 3 sixes are roughly:
一个简单的测试是骰子游戏。 假设用一个骰子掷出六个骰子的几率是六分之一,如果我同时掷三个骰子100次,则0、1、2和3个骰子的期望值大致为:
- 0 sixes = 57.9 times 0秒= 57.9倍
- 1 sixes = 34.7 times 1个6 = 34.7倍
- 2 sixes = 6.9 times 2个6 = 6.9倍
- 3 sixes = 0.5 times 3个6 = 0.5次
Here is the code to reproduce the dice roll 1.000.000 times:
这是将骰子掷出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);
Testing the code above with PHP7 random_int
and the simple rand
function might produce:
使用PHP7 random_int
和简单的rand
函数测试以上代码可能会产生:
Sixes | expected | random_int | rand |
---|---|---|---|
0 | 579000 | 579430 | 578179 |
1 | 347000 | 346927 | 347620 |
2 | 69000 | 68985 | 69586 |
3 | 5000 | 4658 | 4615 |
Sixes | 预期 | random_int | rand |
---|---|---|---|
0 | 579000 | 579430 | 578179 |
1个 | 347000 | 346927 | 347620 |
2 | 69000 | 68985 | 69586 |
3 | 5000 | 4658 | 4615 |
To see a better comparison between rand
and random_int
we can plot the results in a graph applying a formula to increase the differences between values: php result - expected result / sqrt(expected)
.
为了更好地比较rand
和random_int
我们可以将结果绘制在图形中,并应用公式来增加值之间的差异: php result - expected result / sqrt(expected)
。
The resulting graph will be:
结果图将是:
(values close to zero are better)
(接近零的值更好)
Even if the three sixes combination doesn’t perform well, and the test is too easy for a real application we can clearly see that random_int
performs better than rand
. Furthermore, the security of an application is increased by the absence of predictable, repeatable behaviors in the random number generator adopted.
即使三个6个组合的效果不佳,并且测试对于实际应用来说太简单了,我们也可以清楚地看到random_int
性能优于rand
。 此外,由于在采用的随机数生成器中没有可预测的,可重复的行为,因此提高了应用程序的安全性。
PHP 5呢? (What about PHP 5?)
By default, PHP 5 does not provide any strong pseudo-random number generators. In reality, there are some options like openssl_random_pseudo_bytes()
, mcrypt_create_iv()
or directly use the /dev/random
or /dev/urandom
devices with fread()
. There are also packages like RandomLib or libsodium.
默认情况下,PHP 5不提供任何强大的伪随机数生成器。 实际上,有一些选项,例如openssl_random_pseudo_bytes()
, mcrypt_create_iv()
或直接将/dev/random
或/dev/urandom
设备与fread()
。 也有像RandomLib或libsodium这样的软件包。
If you want to start using a good random number generator and at the same time be PHP 7-ready you can use the Paragon Initiative Enterprises random_compat
library. The random_compat
library allows the use of random_bytes()
and random_int()
in your PHP 5.x project.
如果您想开始使用一个好的随机数生成器,并且同时准备使用PHP 7,则可以使用Paragon Initiative Enterprises的random_compat
库。 random_compat
库允许在PHP 5.x项目中使用random_bytes()
和random_int()
。
The library can be installed via Composer:
该库可以通过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)
The random_compat
library uses a different preference order compared to the PHP 7 one:
与PHP 7相比, random_compat
库使用不同的首选项顺序:
fread()
/dev/urandom
if availablefread()
/dev/urandom
如果可用)mcrypt_create_iv($bytes, MCRYPT_CREATE_IV)
mcrypt_create_iv($bytes, MCRYPT_CREATE_IV)
COM('CAPICOM.Utilities.1')->GetRandom()
COM('CAPICOM.Utilities.1')->GetRandom()
openssl_random_pseudo_bytes()
openssl_random_pseudo_bytes()
For more information about why this order has been used, I suggest reading the documentation.
有关为何使用此命令的更多信息,建议阅读文档 。
A simple use of the library to generate a password can be:
使用该库生成密码的简单用法可以是:
$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
结论 (Conclusion)
You should always apply a cryptographically secure pseudo-random number generator, and the random_compat
lib provides a good implementation for this.
您应该始终应用加密安全的伪随机数生成器,并且random_compat
lib random_compat
提供了一个很好的实现。
If you want to use a reliable random data source, as you saw in the article, the suggestion is to start as soon as possible with random_int
and random_bytes
.
如您在文章中所见,如果您想使用可靠的随机数据源,建议尽快从random_int
和random_bytes
。
Questions or comments? Leave them below!
有疑问或意见吗? 把它们留在下面!
进一步阅读 (Further Reading)
Description | Link |
---|---|
Die Hard Test | https://en.wikipedia.org/wiki/Diehard_tests |
Chi-square test with dice example | http://bit.ly/1Mrptf5 |
Kolmogorov-Smirnov Test | https://en.wikipedia.org/wiki/Kolmogorov-Smirnov_test |
Spectral Test | http://random.mat.sbg.ac.at/tests/theory/spectral/ |
RaBiGeTe test suite | http://cristianopi.altervista.org/RaBiGeTe_MT |
Random Number Generation In PHP (2011) | http://blog.ircmaxell.com/2011/07/random-number-generation-in-php.html |
Testing RNG part 1 and 2 | http://ubm.io/1Ot46vL http://ubm.io/1VNzh3N |
描述 | 链接 |
---|---|
硬模测试 | https://en.wikipedia.org/wiki/Diehard_tests |
卡方检验与骰子示例 | http://bit.ly/1Mrptf5 |
柯尔莫哥洛夫-斯米尔诺夫检验 | https://zh.wikipedia.org/wiki/科尔摩戈罗夫-Smirnov_test |
光谱测试 | http://random.mat.sbg.ac.at/tests/theory/spectral/ |
RaBiGeTe测试套件 | http://cristianopi.altervista.org/RaBiGeTe_MT |
PHP中的随机数生成(2011) | http://blog.ircmaxell.com/2011/07/random-number-generation-in-php.html |
测试RNG第1部分和第2部分 | http://ubm.io/1Ot46vL http://ubm.io/1VNzh3N |
致谢 (Acknowledgements)
Many thanks to the following peer reviewers for their help with this article!
非常感谢以下同行审稿人对本文的帮助!
php 获取a-z中随机