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
phpwind中的数据库操作类
Jan 02 PHP
PHP获取http请求的头信息实现步骤
Dec 16 PHP
php 判断是否是中文/英文/数字示例代码
Sep 30 PHP
教你如何开启shopnc b2b2c 伪静态
Oct 21 PHP
PIGCMS 如何关闭聊天机器人
Feb 12 PHP
php实现简单的MVC框架实例
Sep 23 PHP
PHP实现基于mysqli的Model基类完整实例
Apr 08 PHP
PHP批量获取网页中所有固定种子链接的方法
Nov 18 PHP
浅谈PHP的排列组合(如输入a,b,c 输出他们的全部组合)
Mar 14 PHP
PHP实现的回溯算法示例
Aug 15 PHP
thinkPHP框架实现的短信接口验证码功能示例
Jun 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
php简单封装了一些常用JS操作
2007/02/25 PHP
dedecms系统常用术语汇总
2007/04/03 PHP
木翼下载系统中说明的PHP安全配置方法
2007/06/16 PHP
第二章 PHP入门基础之php代码写法
2011/12/30 PHP
解决PHP4.0 和 PHP5.0类构造函数的兼容问题
2013/08/01 PHP
编写PHP脚本过滤用户上传的图片
2015/07/03 PHP
PHP二分查找算法示例【递归与非递归方法】
2016/09/29 PHP
PHP在线打包下载功能示例
2016/10/15 PHP
js网页版计算器的简单实现
2013/07/02 Javascript
两个select多选模式的选项相互移动(示例代码)
2014/01/11 Javascript
javascript面向对象特性代码实例
2014/06/12 Javascript
js实现超简单的展开、折叠目录代码
2015/08/28 Javascript
用jQuery实现优酷首页轮播图
2017/01/09 Javascript
Bootstrap多级菜单的实现代码
2017/05/23 Javascript
vue.js实现条件渲染的实例代码
2017/06/22 Javascript
深入了解JavaScript 私有化
2019/05/30 Javascript
vue项目从node8.x升级到12.x后的问题解决
2019/10/25 Javascript
NodeJS模块Buffer原理及使用方法解析
2020/11/11 NodeJs
通过python下载FTP上的文件夹的实现代码
2013/02/10 Python
Python下载指定页面上图片的方法
2016/05/12 Python
3个用于数据科学的顶级Python库
2018/09/29 Python
对python中数据集划分函数StratifiedShuffleSplit的使用详解
2018/12/11 Python
python3.7 使用pymssql往sqlserver插入数据的方法
2019/07/08 Python
Python符号计算之实现函数极限的方法
2019/07/15 Python
Python类如何定义私有变量
2020/02/03 Python
CSS3中的content属性使用示例
2015/07/20 HTML / CSS
HTML5 Canvas中绘制矩形实例
2015/01/01 HTML / CSS
路德维希•贝克(LUDWIG BECK)中文官网:德国大型美妆百货
2020/09/19 全球购物
实习教师自我鉴定
2013/12/09 职场文书
合作意向书格式及范文
2014/03/31 职场文书
表彰大会策划方案
2014/05/13 职场文书
个人委托书
2014/07/31 职场文书
2014年物流工作总结
2014/11/25 职场文书
中秋节晚会开场白
2015/05/29 职场文书
2016大学迎新晚会开场白
2015/11/24 职场文书
vue实现登陆页面开发实践
2022/05/30 Vue.js