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 cdata 处理(详细介绍)
Jul 05 PHP
模板引擎smarty工作原理以及使用示例
May 25 PHP
php中heredoc与nowdoc介绍
Dec 25 PHP
PHP中$this和$that指针使用实例
Jan 06 PHP
php获取客户端电脑屏幕参数的方法
Jan 09 PHP
PHP计算日期相差天数实例分析
Feb 23 PHP
PHP创建多级目录的两种方法
Oct 28 PHP
Laravel中前端js上传图片到七牛云的示例代码
Sep 04 PHP
详解PHP队列的实现
Mar 14 PHP
Laravel框架查询构造器简单示例
May 08 PHP
PHP中类与对象功能、用法实例解读
Mar 27 PHP
thinkphp 框架数据库切换实现方法分析
May 18 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实现带读写分离功能的MySQL类完整实例
2016/07/28 PHP
php计算给定日期所在周的开始日期和结束日期示例
2017/02/06 PHP
thinkphp框架无限级栏目的排序功能实现方法示例
2020/03/29 PHP
JS 面向对象的5钟写法
2009/07/31 Javascript
Extjs ajax同步请求时post方式参数发送方式
2009/08/05 Javascript
基于jQuery的的一个隔行变色,鼠标移动变色的小插件
2010/07/06 Javascript
jsp+javascript打造级连菜单的实例代码
2013/06/14 Javascript
基于SVG的web页面图形绘制API介绍及编程演示
2013/06/28 Javascript
关闭时刷新父窗口两种方法
2014/05/07 Javascript
jsonp跨域请求实现示例
2017/03/13 Javascript
jQuery实现 RadioButton做必选校验功能
2017/06/15 jQuery
使用react实现手机号的数据同步显示功能的示例代码
2018/04/03 Javascript
node使用Mongoose类库实现简单的增删改查
2018/11/08 Javascript
详解Vue组件插槽的使用以及调用组件内的方法
2018/11/13 Javascript
vue 路由懒加载中给 Webpack Chunks 命名的方法
2020/04/24 Javascript
vue+echarts实现动态折线图的方法与注意
2020/09/01 Javascript
利用Python获取赶集网招聘信息前篇
2016/04/18 Python
python对象及面向对象技术详解
2016/07/19 Python
Python 含参构造函数实例详解
2017/05/25 Python
Python编程对列表中字典元素进行排序的方法详解
2017/05/26 Python
linecache模块加载和缓存文件内容详解
2018/01/11 Python
Python 实现在文件中的每一行添加一个逗号
2018/04/29 Python
Python实现Event回调机制的方法
2019/02/13 Python
Python List cmp()知识点总结
2019/02/18 Python
GitHub 热门:Python 算法大全,Star 超过 2 万
2019/04/29 Python
python实现图片九宫格分割
2021/03/07 Python
pycharm设置当前工作目录的操作(working directory)
2020/02/14 Python
python实现简单井字棋小游戏
2020/03/05 Python
Nginx+Uwsgi+Django 项目部署到服务器的思路详解
2020/05/08 Python
HTML5边玩边学(2)基础绘图实现方法
2010/09/21 HTML / CSS
新加坡航空官方网站:Singapore Airlines
2016/10/13 全球购物
教师自我评价范例
2013/09/24 职场文书
服装促销活动方案
2014/02/23 职场文书
初中新生军训方案
2014/05/13 职场文书
经典搞笑版检讨书
2015/02/19 职场文书
员工拾金不昧表扬稿
2015/05/05 职场文书