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程序?
Dec 08 PHP
PHP的分页功能
Mar 21 PHP
工厂模式在Zend Framework中应用介绍
Jul 10 PHP
CI框架源码阅读,系统常量文件constants.php的配置
Feb 28 PHP
ThinkPHP的Widget扩展实例
Jun 19 PHP
PHP实现将MySQL重复ID二维数组重组为三维数组的方法
Aug 01 PHP
php compact 通过变量创建数组
Nov 15 PHP
什么是PHP文件?如何打开PHP文件?
Jun 27 PHP
PHP自定义函数实现数组比较功能示例
Oct 19 PHP
PHP7中I/O模型内核剖析详解
Apr 14 PHP
PHP下载大文件失败并限制下载速度的实例代码
May 10 PHP
php操作redis数据库常见方法实例总结
Feb 20 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
磨咖啡豆的密诀
2021/03/03 冲泡冲煮
PHP错误WARNING: SESSION_START() [FUNCTION.SESSION-START]解决方法
2014/05/04 PHP
ThinkPHP基本的增删查改操作实例教程
2014/08/22 PHP
javascript 全角转换实现代码
2009/07/17 Javascript
jquery中实现标签切换效果的代码
2011/03/01 Javascript
ASP.NET jQuery 实例6 (实现CheckBoxList成员全选或全取消)
2012/01/13 Javascript
30个让人兴奋的视差滚动(Parallax Scrolling)效果网站
2012/03/04 Javascript
jquery模拟SELECT下拉框取值效果
2013/10/23 Javascript
jQuery自定义事件的简单实现代码
2014/01/27 Javascript
深入理解JavaScript系列(50):Function模式(下篇)
2015/03/04 Javascript
浅谈javascript基础之客户端事件驱动
2016/06/10 Javascript
Vue.js结合Ueditor富文本编辑器的实例代码
2017/07/11 Javascript
Angular弹出模态框的两种方式
2017/10/19 Javascript
Js中使用正则表达式验证输入是否有特殊字符
2018/09/07 Javascript
JavaScript使用localStorage存储数据
2019/09/25 Javascript
Python linecache.getline()读取文件中特定一行的脚本
2008/09/06 Python
python实现事件驱动
2018/11/21 Python
python文件转为exe文件的方法及用法详解
2019/07/08 Python
Python socket模块方法实现详解
2019/11/05 Python
python通过文本在一个图中画多条线的实例
2020/02/21 Python
解决Keras自带数据集与预训练model下载太慢问题
2020/06/12 Python
CSS3 伪类选择器 nth-child()说明
2010/07/10 HTML / CSS
通过css3的filter滤镜改变png图片的颜色的示例代码
2020/05/06 HTML / CSS
html5的canvas实现3d雪花飘舞效果
2013/12/27 HTML / CSS
Abbott Lyon官网:女士手表、珠宝及配件
2020/12/26 全球购物
上海期货面试题
2014/01/31 面试题
幼儿教师研修感言
2014/02/12 职场文书
会计岗位描述
2014/02/22 职场文书
组工干部演讲稿
2014/09/02 职场文书
税务干部群众路线教育实践活动自我剖析材料
2014/09/21 职场文书
2014年幼儿园园长工作总结
2014/12/17 职场文书
2015年毕业生自荐信范文
2015/03/24 职场文书
食品药品安全责任书
2015/05/11 职场文书
收入证明怎么写
2015/06/12 职场文书
Nginx实现高可用集群构建(Keepalived+Haproxy+Nginx)
2021/05/27 Servers
总结一些Java常用的加密算法
2021/06/11 Java/Android