热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

CodeIgniter-Security的CSRFhash生成功能

Security类中get_random_bytes()方法负责随机生成字符串,用于CSRF验证的hash值。publicfunctionget_random_bytes($le

Security类中get_random_bytes()方法负责随机生成字符串,用于 CSRF 验证的hash值。

public function get_random_bytes($length)
{
if (empty($length) OR ! ctype_digit((string) $length))
{
return FALSE;
}

if (defined('MCRYPT_DEV_URANDOM') && ($output = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM)) !== FALSE)
{
return $output;
}

if (is_readable('/dev/urandom') && ($fp = fopen('/dev/urandom', 'rb')) !== FALSE)
{
// Try not to waste entropy ...
is_php('5.4') && stream_set_chunk_size($fp, $length);
$output = fread($fp, $length);
fclose($fp);
if ($output !== FALSE)
{
return $output;
}
}

if (function_exists('openssl_random_pseudo_bytes'))
{
return openssl_random_pseudo_bytes($length);
}

return FALSE;
}

从上面的代码可以看出,程序调用的优先级 mcrypt_create_iv -> /dev/urandom ->openssl_random_pseudo_bytes.  那么这三种调用方式有什么区别呢?

首先,查看 mcrypt_create_iv 函数源码 (/ext/mcrypt/mcrypt.c).

PHP_FUNCTION(mcrypt_create_iv)
{
char *iv;
long source = RANDOM;
long size;
int n = 0;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &size, &source) == FAILURE) {
return;
}
if (size <= 0 || size >= INT_MAX) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create an IV with a size of less than 1 or greater than %d", INT_MAX);
RETURN_FALSE;
}

iv = ecalloc(size + 1, 1);

if (source == RANDOM || source == URANDOM) {
#if PHP_WIN32
/* random/urandom equivalent on Windows */
BYTE *iv_b = (BYTE *) iv;
if (php_win32_get_random_bytes(iv_b, (size_t) size) == FAILURE){
efree(iv);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not gather sufficient random data");
RETURN_FALSE;
}
n = size;
#else
int fd;
size_t read_bytes = 0;

fd = open(source == RANDOM ? "/dev/random" : "/dev/urandom", O_RDONLY);
if (fd <0) {
efree(iv);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot open source device");
RETURN_FALSE;
}
while (read_bytes n = read(fd, iv + read_bytes, size - read_bytes);
if (n <0) {
break;
}
read_bytes += n;
}
n = read_bytes;
close(fd);
if (n efree(iv);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not gather sufficient random data");
RETURN_FALSE;
}
#endif
} else {
n = size;
while (size) {
iv[--size] = (char) (255.0 * php_rand(TSRMLS_C) / RAND_MAX);
}
}
RETURN_STRINGL(iv, n, 0);
}

mcrypt_create_iv函数接受两个参数。在linux操作系统下, source == RANDOM 时 调用 "/dev/random"获取随机数, 当 source == URANDOM时,则调用“/dev/urandom”。

回看get_random_bytes函数代码, mcrypt_create_iv的第二个参数值为MCRYPT_DEV_URANDOM,实际上,调用"dev/urandom"来获取随机数。

那么相比直接调用dev/urandom获取随机数,mcrypt_create_iv 兼容性更好。


再来看看openssl_random_pseudo_bytes函数源码(ext/openssl/openssl.c):

PHP_FUNCTION(openssl_random_pseudo_bytes)
{
long buffer_length;
unsigned char *buffer = NULL;
zval *zstrong_result_returned = NULL;
int strong_result = 0;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|z", &buffer_length, &zstrong_result_returned) == FAILURE) {
return;
}

if (buffer_length <= 0) {
RETURN_FALSE;
}

if (zstrong_result_returned) {
zval_dtor(zstrong_result_returned);
ZVAL_BOOL(zstrong_result_returned, 0);
}

buffer = emalloc(buffer_length + 1);

if ((strong_result = RAND_pseudo_bytes(buffer, buffer_length)) <0) {
efree(buffer);
RETURN_FALSE;
}

buffer[buffer_length] = 0;
RETVAL_STRINGL((char *)buffer, buffer_length, 0);

if (zstrong_result_returned) {
ZVAL_BOOL(zstrong_result_returned, strong_result);
}
}

openssl_random_pseudo_bytes内部实际调用RAND_pseudo_byte()生成随机数(RAND_pseudo_bytes不作介绍,有兴趣的童鞋可参考http://blog.csdn.net/sunspider107/article/details/7364770资料).


以上就是get_random_bytes()生成随机数三种方式的介绍,下面稍带简单地介绍 /dev/random 与 /dev/urandom 区别。

/dev/random 与 /dev/urandom 都是linux系统随机数生成器。唯一的区别是 当linux 熵池随机数不多时,读取/dev/random 时 会发生阻塞, 而/dev/urandom 不会。


总结:

在生成环境使用中,考虑到平台的兼容性,尽量使用 mcrypt_create_iv 函数获取随机数,尽量杜绝使用"/dev/random "方式。



推荐阅读
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 本文介绍了一个适用于PHP应用快速接入TRX和TRC20数字资产的开发包,该开发包支持使用自有Tron区块链节点的应用场景,也支持基于Tron官方公共API服务的轻量级部署场景。提供的功能包括生成地址、验证地址、查询余额、交易转账、查询最新区块和查询交易信息等。详细信息可参考tron-php的Github地址:https://github.com/Fenguoz/tron-php。 ... [详细]
  • OpenMap教程4 – 图层概述
    本文介绍了OpenMap教程4中关于地图图层的内容,包括将ShapeLayer添加到MapBean中的方法,OpenMap支持的图层类型以及使用BufferedLayer创建图像的MapBean。此外,还介绍了Layer背景标志的作用和OMGraphicHandlerLayer的基础层类。 ... [详细]
  • 本文详细介绍了git常用命令及其操作方法,包括查看、添加、提交、删除、找回等操作,以及如何重置修改文件、抛弃工作区修改、将工作文件提交到本地暂存区、从版本库中删除文件等。同时还介绍了如何从暂存区恢复到工作文件、恢复最近一次提交过的状态,以及如何合并多个操作等。 ... [详细]
  • ***byte(字节)根据长度转成kb(千字节)和mb(兆字节)**parambytes*return*publicstaticStringbytes2kb(longbytes){ ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
  • Android日历提醒软件开源项目分享及使用教程
    本文介绍了一款名为Android日历提醒软件的开源项目,作者分享了该项目的代码和使用教程,并提供了GitHub项目地址。文章详细介绍了该软件的主界面风格、日程信息的分类查看功能,以及添加日程提醒和查看详情的界面。同时,作者还提醒了读者在使用过程中可能遇到的Android6.0权限问题,并提供了解决方法。 ... [详细]
  • 开源Keras Faster RCNN模型介绍及代码结构解析
    本文介绍了开源Keras Faster RCNN模型的环境需求和代码结构,包括FasterRCNN源码解析、RPN与classifier定义、data_generators.py文件的功能以及损失计算。同时提供了该模型的开源地址和安装所需的库。 ... [详细]
  • Python使用Pillow包生成验证码图片的方法
    本文介绍了使用Python中的Pillow包生成验证码图片的方法。通过随机生成数字和符号,并添加干扰象素,生成一幅验证码图片。需要配置好Python环境,并安装Pillow库。代码实现包括导入Pillow包和随机模块,定义随机生成字母、数字和字体颜色的函数。 ... [详细]
  • 本文介绍了在Cpp中将字符串形式的数值转换为int或float等数值类型的方法,主要使用了strtol、strtod和strtoul函数。这些函数可以将以null结尾的字符串转换为long int、double或unsigned long类型的数值,且支持任意进制的字符串转换。相比之下,atoi函数只能转换十进制数值且没有错误返回。 ... [详细]
  • 本文介绍了贝叶斯垃圾邮件分类的机器学习代码,代码来源于https://www.cnblogs.com/huangyc/p/10327209.html,并对代码进行了简介。朴素贝叶斯分类器训练函数包括求p(Ci)和基于词汇表的p(w|Ci)。 ... [详细]
  • #define_CRT_SECURE_NO_WARNINGS#includelist.h#includevoidSListInit(PNode*pHead ... [详细]
  • Python教学练习二Python1-12练习二一、判断季节用户输入月份,判断这个月是哪个季节?3,4,5月----春 ... [详细]
author-avatar
王耀
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有