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
main.php
Dec 09 PHP
wiki-shan写的php在线加密的解密程序
Sep 07 PHP
PHP中的事务使用实例
May 26 PHP
PHP编程开发怎么提高编程效率 提高PHP编程技术
Nov 09 PHP
php版微信自动获取收货地址api用法示例
Sep 22 PHP
PHP简单数据库操作类实例【支持增删改查及链式操作】
Oct 10 PHP
php 三元运算符实例详细介绍
Dec 15 PHP
php封装的验证码类分享
Feb 26 PHP
PHP 布尔值的自增与自减的实现方法
May 03 PHP
PHP5.0 TIDY_PARSE_FILE缓冲区溢出漏洞的解决方案
Oct 14 PHP
php的RSA加密解密算法原理与用法分析
Jan 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
杏林同学录(六)
2006/10/09 PHP
Yii数据库缓存实例分析
2016/03/29 PHP
PHP DB 数据库连接类定义与用法示例
2019/03/11 PHP
PHP+redis实现微博的拉模型案例详解
2019/07/10 PHP
PHP检测一个数组有没有定义的方法步骤
2019/07/20 PHP
jquery获得页面元素的坐标值实现思路及代码
2013/04/15 Javascript
js中return false(阻止)的用法
2013/08/14 Javascript
javascript:void(0)使用探讨
2013/08/27 Javascript
vue分页组件table-pagebar使用实例解析
2020/11/15 Javascript
深入理解Webpack 中路径的配置
2017/06/17 Javascript
Vue实例中生命周期created和mounted的区别详解
2017/08/25 Javascript
jQuery选择器之子元素过滤选择器
2017/09/28 jQuery
Node错误处理笔记之挖坑系列教程
2018/06/05 Javascript
详解nodejs 开发企业微信第三方应用入门教程
2019/03/12 NodeJs
mpvue 页面预加载新增preLoad生命周期的两种方式
2019/10/17 Javascript
Python中字典(dict)和列表(list)的排序方法实例
2014/06/16 Python
python利用beautifulSoup实现爬虫
2014/09/29 Python
python插入排序算法实例分析
2015/07/03 Python
Python实现的弹球小游戏示例
2017/08/01 Python
Python+matplotlib实现填充螺旋实例
2018/01/15 Python
python学习基础之循环import及import过程
2018/04/22 Python
便捷提取python导入包的属性方法
2018/10/15 Python
Python给图像添加噪声具体操作
2019/03/03 Python
详解pandas的外部数据导入与常用方法
2019/05/01 Python
python opencv 批量改变图片的尺寸大小的方法
2019/06/28 Python
CSS3动画之利用requestAnimationFrame触发重新播放功能
2019/09/11 HTML / CSS
Get The Label中文官网:英国运动时尚购物平台
2017/04/19 全球购物
BISSELL官网:北美吸尘器第一品牌
2019/03/14 全球购物
Contém1g官网:巴西彩妆品牌
2020/01/17 全球购物
SCHIESSER荷兰官方网站:德国内衣专家
2020/10/09 全球购物
化工专业个人的求职信范文
2013/11/28 职场文书
化学教育专业求职信
2014/07/08 职场文书
公司总经理助理岗位职责
2014/07/09 职场文书
团队拓展活动方案
2014/08/28 职场文书
mysql 直接拷贝data 目录下文件还原数据的实现
2021/07/25 MySQL
教你修复 Win11应用商店加载空白问题
2021/12/06 数码科技