PHP更安全的密码加密机制Bcrypt详解


Posted in PHP onJune 18, 2017

前言

我们常常为了避免在服务器受到攻击,数据库被拖库时,用户的明文密码不被泄露,一般会对密码进行单向不可逆加密——哈希。

常见的方式是:

哈希方式 加密密码
md5(‘123456') e10adc3949ba59abbe56e057f20f883e
md5(‘123456' . ($salt = ‘salt')) 207acd61a3c1bd506d7e9a4535359f8a
sha1(‘123456') 40位密文
hash(‘sha256', ‘123456') 64位密文
hash(‘sha512', ‘123456') 128位密文

密文越长,在相同机器上,进行撞库消耗的时间越长,相对越安全。

比较常见的哈希方式是 md5 + 盐,避免用户设置简单密码,被轻松破解。

password_hash

但是,现在要推荐的是 password_hash() 函数,可以轻松对密码实现加盐加密,而且几乎不能破解。

$password = '123456';
 
var_dump(password_hash($password, PASSWORD_DEFAULT));
var_dump(password_hash($password, PASSWORD_DEFAULT));

password_hash 生成的哈希长度是 PASSWORD_BCRYPT —— 60位,PASSWORD_DEFAULT —— 60位 ~ 255位。PASSWORD_DEFAULT 取值跟 php 版本有关系,会等于其他值,但不影响使用。

每一次 password_hash 运行结果都不一样,因此需要使用 password_verify 函数进行验证。

$password = '123456';
 
$hash = password_hash($password, PASSWORD_DEFAULT);
var_dump(password_verify($password, $hash));

password_hash 会把计算 hash 的所有参数都存储在 hash 结果中,可以使用 password_get_info 获取相关信息。

$password = '123456';
$hash = password_hash($password, PASSWORD_DEFAULT);
var_dump(password_get_info($hash));

输出

array(3) {
 ["algo"]=>
 int(1)
 ["algoName"]=>
 string(6) "bcrypt"
 ["options"]=>
 array(1) {
 ["cost"]=>
 int(10)
 }
}

注意:不包含 salt

可以看出我当前版本的 PHP 使用 PASSWORD_DEFAULT 实际是使用 PASSWORD_BCRYPT

password_hash($password, $algo, $options) 的第三个参数 $options 支持设置至少 22 位的 salt。但仍然强烈推荐使用 PHP 默认生成的 salt,不要主动设置 salt。

当要更新加密算法和加密选项时,可以通过 password_needs_rehash 判断是否需要重新加密,下面的代码是一段官方示例

$options = array('cost' => 11);
// Verify stored hash against plain-text password
if (password_verify($password, $hash))
{
 // Check if a newer hashing algorithm is available
 // or the cost has changed
 if (password_needs_rehash($hash, PASSWORD_DEFAULT, $options))
 {
  // If so, create a new hash, and replace the old one
  $newHash = password_hash($password, PASSWORD_DEFAULT, $options);
 }
 // Log user in
}

password_needs_rehash 可以理解为比较 $algo + $optionpassword_get_info($hash) 返回值。

password_hash 运算慢

password_hash 是出了名的运行慢,也就意味着在相同时间内,密码重试次数少,泄露风险降低。

$password = '123456';
var_dump(microtime(true));
var_dump(password_hash($password, PASSWORD_DEFAULT));
var_dump(microtime(true));
 
echo "\n";
 
var_dump(microtime(true));
var_dump(md5($password));
for ($i = 0; $i < 999; $i++)
{
 md5($password);
}
var_dump(microtime(true));

输出

float(1495594920.7034)
string(60) "$2y$10$9ZLvgzqmiZPEkYiIUchT6eUJqebekOAjFQO8/jW/Q6DMrmWNn0PDm"
float(1495594920.7818)

float(1495594920.7818)
string(32) "e10adc3949ba59abbe56e057f20f883e"
float(1495594920.7823)

password_hash 运行一次耗时 784 毫秒, md5 运行 1000 次耗时 5 毫秒。这是一个非常粗略的比较,跟运行机器有关,但也可以看出 password_hash 运行确实非常慢。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
非常好的php目录导航文件代码
Oct 09 PHP
实用函数9
Nov 08 PHP
PHP下用rmdir实现删除目录的三种方法小结
Apr 20 PHP
php 应用程序安全防范技术研究
Sep 25 PHP
php中字符集转换iconv函数使用总结
Oct 11 PHP
PHP数组相关函数汇总
Mar 24 PHP
php打包网站并在线压缩为zip
Feb 13 PHP
深入解析PHP的Yii框架中的event事件机制
Mar 17 PHP
PHP邮箱验证示例教程
Jun 01 PHP
PHP面向对象之工作单元(实例讲解)
Jun 26 PHP
php使用curl_init()和curl_multi_init()多线程的速度比较详解
Aug 15 PHP
php中目录操作opendir()、readdir()及scandir()用法示例
Jun 08 PHP
Laravel中log无法写入问题的解决
Jun 17 #PHP
php下载远程大文件(获取远程文件大小)的实例
Jun 17 #PHP
浅谈ThinkPHP5.0版本和ThinkPHP3.2版本的区别
Jun 17 #PHP
PHP 7安装调试工具Xdebug扩展的方法教程
Jun 17 #PHP
thinkphp查询,3.X 5.0方法(亲试可行)
Jun 17 #PHP
php 生成加密公钥加密私钥实例详解
Jun 16 #PHP
详解yii2使用多个数据库的案例
Jun 16 #PHP
You might like
php中通过smtp发邮件的类,测试通过
2007/01/22 PHP
PHP 中检查或过滤IP地址的实现代码
2011/11/27 PHP
php生成html文件方法总结
2014/12/01 PHP
教你php如何实现验证码
2016/01/20 PHP
Laravel框架FormRequest中重写错误处理的方法
2019/02/18 PHP
JQuery从头学起第二讲
2010/07/04 Javascript
Jquery同辈元素选中/未选中效果的实例代码
2013/08/01 Javascript
jQuery对Select的操作大集合(收藏)
2013/12/28 Javascript
require.js+vue开发微信上传图片组件
2016/10/27 Javascript
详解ES6通过WeakMap解决内存泄漏问题
2018/03/09 Javascript
jQuery+Datatables实现表格批量删除功能【推荐】
2018/10/24 jQuery
基于vue-cli搭建多模块且各模块独立打包的项目
2019/06/12 Javascript
js Array.slice的8种不同用法示例
2019/07/10 Javascript
vue+iview实现文件上传
2020/11/17 Vue.js
python连接sql server乱码的解决方法
2013/01/28 Python
Windows和Linux下使用Python访问SqlServer的方法介绍
2015/03/10 Python
Python中的匿名函数使用简介
2015/04/27 Python
举例详解Python中循环语句的嵌套使用
2015/05/14 Python
Python实现二叉堆
2016/02/03 Python
Python 基础知识之字符串处理
2017/01/06 Python
pandas 将list切分后存入DataFrame中的实例
2018/07/03 Python
Python自动发送邮件的方法实例总结
2018/12/08 Python
django开发post接口简单案例,获取参数值的方法
2018/12/11 Python
Python 操作 ElasticSearch的完整代码
2019/08/04 Python
Python调用C/C++的方法解析
2020/08/05 Python
英国汽车和货车租赁网站:Hertz英国
2016/09/02 全球购物
无畏的旅行:Intrepid Travel
2017/12/20 全球购物
电大毕业生自我鉴定
2013/11/10 职场文书
职代会闭幕词
2015/01/28 职场文书
2015年治庸问责工作总结
2015/07/27 职场文书
体育教师教学随笔
2015/08/15 职场文书
2019年公司快递收发管理制度模板
2019/11/20 职场文书
python实现web邮箱扫描的示例(附源码)
2021/03/30 Python
Python破解极验滑动验证码详细步骤
2021/05/21 Python
win10清理dns缓存
2022/04/19 数码科技
js前端面试常见浏览器缓存强缓存及协商缓存实例
2022/06/21 Javascript