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企业级应用之常见缓存技术篇
Jan 27 PHP
PHP乱码问题,UTF-8乱码常见问题小结
Apr 09 PHP
PHP中数字检测is_numeric与ctype_digit的区别介绍
Oct 04 PHP
深入php多态的实现详解
Jun 09 PHP
PHP的一个完美GIF等比缩放类,附带去除缩放黑背景
Apr 01 PHP
PHP伪静态Rewrite设置之APACHE篇
Jul 30 PHP
destoon实现调用图文新闻的方法
Aug 21 PHP
Linux系统下php获得系统分区信息的方法
Mar 30 PHP
WampServer搭建php环境时遇到的问题汇总
Jul 23 PHP
Symfony2使用第三方库Upload制作图片上传实例详解
Feb 04 PHP
php读取torrent种子文件内容的方法(测试可用)
May 03 PHP
php mysql实现mysql_select_db选择数据库
Dec 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详解ASCII码对照表与字符转换
2011/12/05 PHP
zend framework配置操作数据库实例分析
2012/12/06 PHP
php的POSIX 函数以及进程测试的深入分析
2013/06/03 PHP
php实现设计模式中的单例模式详解
2014/10/11 PHP
10款实用的PHP开源工具
2015/10/23 PHP
修复ShopNC使用QQ 互联时提示100010 错误
2015/11/08 PHP
yii2.0使用Plupload实现带缩放功能的多图上传
2015/12/22 PHP
PHP正则表达式过滤html标签属性(DEMO)
2016/05/04 PHP
js判断背景图片是否加载成功使用img的width实现
2013/05/29 Javascript
Visual Studio中js调试的方法图解
2014/06/30 Javascript
jquery插件NProgress.js制作网页加载进度条
2015/06/05 Javascript
详解JavaScript中的every()方法
2015/06/08 Javascript
整理Javascript基础语法学习笔记
2015/11/29 Javascript
jquery自适应布局的简单实例
2016/05/28 Javascript
微信小程序使用canvas的画图操作示例
2019/01/18 Javascript
微信小程序生成分享海报方法(附带二维码生成)
2019/03/29 Javascript
浅谈监听单选框radio改变事件(和layui中单选按钮改变事件)
2019/09/10 Javascript
微信小程序实现滑动翻页效果(完整代码)
2019/12/06 Javascript
解决Nuxt使用axios跨域问题
2020/07/06 Javascript
[05:08]顺网杯ISS-DOTA2赛歌 少女偶像Lunar青春演绎
2013/12/05 DOTA
跟老齐学Python之用Python计算
2014/09/12 Python
详解Python自建logging模块
2018/01/29 Python
Python读取excel中的图片完美解决方法
2018/07/27 Python
使用tensorflow实现线性svm
2018/09/07 Python
使用Python实现微信提醒备忘录功能
2018/12/04 Python
Flask配置Cors跨域的实现
2019/07/12 Python
python:解析requests返回的response(json格式)说明
2020/04/30 Python
弄清Pytorch显存的分配机制
2020/12/10 Python
python 基于UDP协议套接字通信的实现
2021/01/22 Python
股东协议书
2014/04/14 职场文书
先进集体申报材料
2014/12/25 职场文书
社区重阳节活动总结
2015/03/24 职场文书
单位介绍信格式范文
2015/05/04 职场文书
小学大队干部竞选稿
2015/11/20 职场文书
基于go interface{}==nil 的几种坑及原理分析
2021/04/24 Golang
vue实现移动端div拖动效果
2022/03/03 Vue.js