PHP中的随机性——你觉得自己幸运吗?

PHP中的随机性——你觉得自己幸运吗?

你总是应该使用一个密码学上安全的伪随机数生成器,random_compat 库提供了一种好的实现。如果你想要使用可靠的随机数据源,如你在本文所见,建议尽快使用 random_int 和 random_bytes.

作者:邱康来源:码农网|2016-01-21 09:55
     收藏
      分享

网+线下沙龙 | 移动APP模式创新:给你一个做APP的理由>>

本文分析了生成用于加密的随机数的相关问题。 PHP 5没有提供一种简单的机制来生成密码学上强壮的随机数,但是PHP 7通过引入几个CSPRNG函数来解决了这个问题。

Cryptography Randomness in PHP

什么是CSPRNG

引用维基百科,一个密码学上安全的伪随机数发生器(Cryptographically Secure Pseudorandom Number Generator 缩写CSPRNG)是一个伪随机数生成器(PRNG),其生成的伪随机数适用于密码学算法。

CSPRNG可能主要用于:

密钥生成(例如,生成复杂的密钥)

为新用户产生随机的密码

加密系统

获得高级别安全性的一个关键方面就是高品质的随机性

PHP7 中的CSPRNG

php 7引入了两个新函数可以用来实现CSPRNG: random_bytes 和 random_int。

random_bytes 函数返回一个字符串,接受一个int型入参代表返回结果的字节数。

例子:

$bytes = random_bytes(‘10‘);
    var_dump(bin2hex($bytes));
    //possible ouput: string(20) "7dfab0af960d359388e6"

random_int 函数返回一个指定范围内的int型数字。

例子:

var_dump(random_int(1, 100));
    //possible output: 27

后台运行环境

以上函数的随机性不同的取决于环境:

在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次的代码:

$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);

用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次方。

结果图如下:

test random graph

(接近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安装:

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 库和PHP7使用不同的顺序:

fread() /dev/urandom if available
    mcrypt_create_iv($bytes, MCRYPT_CREATE_IV)
    COM(‘CAPICOM.Utilities.1‘)->GetRandom()
    openssl_random_pseudo_bytes()

想知道为什么是这个顺序建议阅读 documentation.

这个库的一个简单应用用来产生密码:

$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.

时间: 2024-10-15 12:14:20

PHP中的随机性——你觉得自己幸运吗?的相关文章

中值统计

这篇主要来讨论下下面这个问题的解法: 无序的整数序列,找出其中值,或者第 K 小的元素! 思考一会,可能这是最快想到的解法,先对数组排序一趟,然后直接取出第k小的元素.这个算法最低的时间复杂度为 O(nlog(n)). 那有没有更加快的算法呢? 先来简单分析下上面这个算法,显然是多做了无用功.因为只要找到第k小的元素,即只要把第k小的位置上的元素找对就可以.而该方法把所有的元素都放在了正确的位置上,这显示是多做了无用功.那么这个问题肯定也是存在更优的解法的. 期望为O(n)的算法 沿着 “将正确

SJTU 3001. 二哥的幸运

Description 二哥是一个挺二的人,在二哥的世界观中,有些数字代表着幸运,如果在某一天二哥能够看到一个幸运数字,那么他将非常高兴.当然,二哥对于幸运的定义也是不同凡响,如果一个数字只包含4或者7两种字符,并且他是一个质数(素数),那么二哥认为他是一个幸运数字.二哥想请聪明的你帮忙回答,给定的一个数是否是幸运数字. Input Format 第1行有1个整数N,表示要测试的数据 Output Format 输出一行字符串,YES或者NO. 表示是否是个幸运数字 Sample Input 4

【转】开始iOS 7中自动布局教程(一)

原文网址:http://www.cocoachina.com/industry/20131203/7462.html 原文:Beginning Auto Layout Tutorial in iOS 7: Part 1 感谢翻译小组成员@answer-huang(博客)热心翻译.如果您有不错的原创或译文,欢迎提交给我们,更欢迎其他朋友加入我们的翻译小组(联系qq:2408167315). ======================================================

开始iOS 7中自动布局教程(一)

你是否曾经想让你的app在横竖屏方向上看起来都表现良好而受挫?是否在做支持iPhone和iPad屏幕布局界面时几近大小便失禁?今天我将给你带来好消息! 一直为大小相同的屏幕设计一个用户界面并不难,但如果屏幕的尺寸改变的话,UI元素的位置和大小也需要相应的做出改变. 到目前为止,如果你的设计相当的复杂,那么你必须编写大量的代码来适应这样的布局.你应该很高兴,现在这样的情况再也不存在了--iOS6为iPhone和iPad带来了一个极好的新特性:自动布局.Xcode 5和 iOS7中对自动布局做出了改

如何实现一个Servlet中的多个功能

如何实现一个Servlet中的多个功能 前言:唉,打脸了,前脚刚说过要跟Servlet正式告别,后脚这不又来了,哈哈,总结出一点东西,纠结了一下还是做个分享吧,学习知识比面子重要,对吧,下回再也不约Servlet了. 需求分析 看下面代码,现在有一个UserServlet,里面有增删改查四个方法,按平常的思维,用一个Servlet实现一个功能,这没毛病,现在问题是一个Servlet中有四个功能,那这该如何去实现呢? package com.my.servlet; import com.my.se

随机模拟(MCMC)

http://cos.name/2013/01/lda-math-mcmc-and-gibbs-sampling/ http://blog.csdn.net/lin360580306/article/details/51240398 随机模拟(或者统计模拟)方法有一个很酷的别名是蒙特卡罗方法(Monte Carlo Simulation).这个方法的发展始于20世纪40年代,和原子弹制造的曼哈顿计划密切相关,当时的几个大牛,包括乌拉姆.冯.诺依曼.费米.费曼.Nicholas Metropoli

LDA-math-MCMC 和 Gibbs Sampling

http://cos.name/2013/01/lda-math-mcmc-and-gibbs-sampling/ 3.1 随机模拟 随机模拟(或者统计模拟)方法有一个很酷的别名是蒙特卡罗方法(Monte Carlo Simulation).这个方法的发展始于20世纪40年代,和原子弹制造的曼哈顿计划密切相关,当时的几个大牛,包括乌拉姆.冯.诺依曼.费米.费曼.Nicholas Metropolis, 在美国洛斯阿拉莫斯国家实验室研究裂变物质的中子连锁反应的时候,开始使用统计模拟的方法,并在最早

MCMC(Markov Chain Monte Carlo) and Gibbs Sampling

MCMC(Markov Chain Monte Carlo) and Gibbs Sampling 1.   随机模拟 随机模拟(或者统计模拟)方法有一个很酷的别名是蒙特卡罗方法(Monte Carlo Simulation).这个方法的发展始于20世纪40年代,和原子弹制造的曼哈顿计划密切相关,当时的几个大牛,包括乌拉姆.冯.诺依曼.费米.费曼.Nicholas Metropolis, 在美国洛斯阿拉莫斯国家实验室研究裂变物质的中子连锁反应的时候,开始使用统计模拟的方法,并在最早的计算机上进行

&lt;转&gt;Burp Suite使用介绍(一) (二) (三)

Getting Started Burp Suite 是用于攻击web 应用程序的集成平台.它包含了许多工具,并为这些工具设计了许多接口,以促进加快攻击应用程序的过程.所有的工具都共享一个能处理并显示HTTP 消息,持久性,认证,代理,日志,警报的一个强大的可扩展的框架.本文主要介绍它的以下特点: 1.Target(目标)——显示目标目录结构的的一个功能 2.Proxy(代理)——拦截HTTP/S的代理服务器,作为一个在浏览器和目标应用程序之间的中间人,允许你拦截,查看,修改在两个方向上的原始数