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 相关文章推荐
PHP4实际应用经验篇(8)
Oct 09 PHP
php 在文件指定行插入数据的代码
May 08 PHP
PHP PDO fetch 模式各种参数的输出结果一览
Jan 07 PHP
WordPress中对访客评论功能的一些优化方法
Nov 24 PHP
详解WordPress中提醒安装插件以及隐藏插件的功能实现
Dec 25 PHP
Laravel最佳分割路由文件(routes.php)的方式
Aug 04 PHP
PHP反射机制原理与用法详解
Feb 15 PHP
php脚本守护进程原理与实现方法详解
Jul 20 PHP
php插件Xajax使用方法详解
Aug 31 PHP
php数据库的增删改查 php与javascript之间的交互
Aug 31 PHP
php swoole多进程/多线程用法示例【基于php7nts版】
Aug 12 PHP
laravel5表单唯一验证的实例代码
Sep 30 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新浪微博登录接口用法实例
2014/12/23 PHP
Laravel框架查询构造器简单示例
2019/05/08 PHP
js 字符串转化成数字的代码
2011/06/29 Javascript
js判断运行jsp页面的浏览器类型以及版本示例
2013/10/30 Javascript
不使用jquery实现js打字效果示例分享
2014/01/19 Javascript
jQuery中:reset选择器用法实例
2015/01/04 Javascript
jQuery实现防止提交按钮被双击的方法
2015/03/24 Javascript
关于JS中prototype的理解
2015/09/07 Javascript
Angular开发者指南之入门介绍
2017/03/05 Javascript
jQuery实现可兼容IE6的滚动监听功能
2017/09/20 jQuery
react以create-react-app为基础创建项目
2018/03/14 Javascript
详解vue中点击空白处隐藏div的实现(用指令实现)
2018/04/19 Javascript
使用JS代码实现俄罗斯方块游戏
2018/08/03 Javascript
基于vue中keep-alive缓存问题的解决方法
2018/09/21 Javascript
在PyCharm下使用 ipython 交互式编程的方法
2019/01/17 Python
Python当中的array数组对象实例详解
2019/06/12 Python
分析运行中的 Python 进程详细解析
2019/06/22 Python
基于python的docx模块处理word和WPS的docx格式文件方式
2020/02/13 Python
Python 日期与时间转换的方法
2020/08/01 Python
HTML4和HTML5之间除了相似以外的10个主要不同
2012/12/13 HTML / CSS
HTML5 3D衣服摇摆动画特效
2016/03/17 HTML / CSS
英国最大的独立摄影零售商:Park Cameras
2019/11/27 全球购物
英国第一独立滑雪板商店:The Snowboard Asylum
2020/01/16 全球购物
意大利包包和行李箱销售网站:Bagaglio.it
2021/03/02 全球购物
如何写出高性能的JSP和Servlet
2013/01/22 面试题
Linux文件系统类型
2012/02/15 面试题
软件测试题目
2013/02/27 面试题
高中学生评语大全
2014/04/25 职场文书
党员个人自我评价
2015/03/03 职场文书
圣诞晚会主持词开场白
2015/05/28 职场文书
给朋友的赠语
2015/06/23 职场文书
社会心理学学习心得体会
2016/01/22 职场文书
浅谈自定义校验注解ConstraintValidator
2021/06/30 Java/Android
K8s部署发布Golang应用程序的实现方法
2021/07/16 Golang
python读取mnist数据集方法案例详解
2021/09/04 Python
Tomcat配置访问日志和线程数
2022/05/06 Servers