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字符转义相关函数小结(php下的转义字符串)
Apr 12 PHP
一步一步学习PHP(6) 面向对象
Feb 16 PHP
php 函数中使用static的说明
Jun 01 PHP
thinkphp在低版本Nginx 下支持PATHINFO的方法分享
May 27 PHP
smarty循环嵌套用法示例分析
Jul 19 PHP
PHP实现的激活用户注册验证邮箱功能示例
Jun 06 PHP
浅谈Laravel队列实现原理解决问题记录
Aug 19 PHP
visual studio code 调试php方法(图文详解)
Sep 15 PHP
PHP中的Iterator迭代对象属性详解
Apr 12 PHP
PHP下载大文件失败并限制下载速度的实例代码
May 10 PHP
PHP的JSON封装、转变及输出操作示例
Sep 27 PHP
laravel框架中控制器的创建和使用方法分析
Nov 23 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数组函数
2008/08/18 PHP
php 获取mysql数据库信息代码
2009/03/12 PHP
smarty高级特性之对象的使用方法
2015/12/25 PHP
php微信高级接口群发 多客服
2016/06/23 PHP
PHP编译configure时常见错误的总结
2017/08/17 PHP
Laravel 5.5 的自定义验证对象/类示例代码详解
2017/08/29 PHP
PHP实现的CURL非阻塞调用类
2018/07/26 PHP
PHP强制转化的形式整理
2020/05/22 PHP
JQuery优缺点分析说明
2010/06/09 Javascript
使用jQuery的attr方法来修改onclick值
2014/07/07 Javascript
Javascript中Array用法实例分析
2015/06/13 Javascript
jQuery实现自定义右键菜单的树状菜单效果
2015/09/02 Javascript
基于javascript实现图片切换效果
2016/04/17 Javascript
jquery通过name属性取值的简单实现方法
2016/06/20 Javascript
详解js实现线段交点的三种算法
2016/08/09 Javascript
微信小程序 合法域名校验出错详解及解决办法
2017/03/09 Javascript
Node.js中Bootstrap-table的两种分页的实现方法
2017/09/18 Javascript
快速解决vue-cli不能初始化webpack模板的问题
2018/03/20 Javascript
详解vue挂载到dom上会发生什么
2019/01/20 Javascript
js实现AI五子棋人机大战
2020/05/28 Javascript
使用vue实现通过变量动态拼接url
2020/07/22 Javascript
JS实现拖拽元素时与另一元素碰撞检测
2020/08/27 Javascript
[01:25]DOTA2超级联赛专访iG 将调整状态找回自己
2013/06/05 DOTA
零基础写python爬虫之urllib2中的两个重要概念:Openers和Handlers
2014/11/05 Python
numpy库与pandas库axis=0,axis= 1轴的用法详解
2019/05/27 Python
Django model update的多种用法介绍
2020/03/28 Python
Python解释器以及PyCharm的安装教程图文详解
2020/02/26 Python
简单几步用纯CSS3实现3D翻转效果
2019/01/17 HTML / CSS
香蕉共和国工厂店:Banana Republic Factory
2018/06/09 全球购物
餐饮管理自我介绍信
2014/01/15 职场文书
毕业实习指导教师评语
2014/12/31 职场文书
2015年重阳节主持词
2015/07/04 职场文书
三好学生评选事迹材料(2016精选版)
2016/02/25 职场文书
以MySQL5.7为例了解一下执行计划
2022/04/13 MySQL
Redis如何实现验证码发送 以及限制每日发送次数
2022/04/18 Redis
Redis实现一个账号只能登录一个设备
2022/04/19 Redis