CodeIgniter-Security的CSRF hash生成功能
来源:互联网 发布:gddr5x和hbm2知乎 编辑:程序博客网 时间:2024/06/01 17:30
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;#elseint 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 < size) {n = read(fd, iv + read_bytes, size - read_bytes);if (n < 0) {break;}read_bytes += n;}n = read_bytes;close(fd);if (n < size) {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 "方式。
- CodeIgniter-Security的CSRF hash生成功能
- Spring security下csrf token的认证
- DWR CSRF Security Error
- CSRF Security Error解决办法
- CSRF Security Error解决办法
- CSRF security error
- CSRF Security Error
- Spring Security csrf学习
- springboot security CSRF问题
- security禁用csrf
- spring security的csrf防御机制在ajax中的应用
- 解决Spring Security 表单上传文件CSRF失效的问题
- CSRF攻击预防的Token生成原理
- DWR 弹出 "CSRF Security Error"
- 【bug】CSRF Security Error解决办法
- spring security csrf 学习笔记
- spring boot security csrf ignore
- spring security 的 logout 功能
- php超全局变量
- spark学习
- Javascript严格模式
- 键盘类型
- Android高级开发必读书单
- CodeIgniter-Security的CSRF hash生成功能
- HTML JS转义字符
- iOS sha1加密方法(哈希算法,用于校验数据完整性)以及字符串中含有汉字的情况的加密方法
- Guava Cache 缓存数据被移除后的监听器RemovalListener
- curl命令上传下载文件
- vs中无法加入断点进行调试的解决方案
- js延迟加载方式
- AJAX的学习笔记
- sql 聚合函数 sum 消息 8115,级别 16 将 expression 转换为数据类型 int 时出现算术溢出错误。