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
php 无限级 SelectTree 类
May 19 PHP
PHP CKEditor 上传图片实现代码
Nov 06 PHP
PHP数组的交集array_intersect(),array_intersect_assoc(),array_inter_key()函数的小问题
May 29 PHP
允许phpmyadmin空密码登录的配置方法
May 29 PHP
VB中的RasEnumConnections函数返回632错误解决方法
Jul 29 PHP
phpmailer绑定邮箱的实现方法
Dec 01 PHP
基于win2003虚拟机中apache服务器的访问
Aug 01 PHP
PHP 访问数据库配置通用方法(json)
May 20 PHP
详解Laravel5.6 Passport实现Api接口认证
Jul 27 PHP
Yii2框架实现利用mpdf创建pdf文件功能示例
Feb 08 PHP
linux mint下安装phpstorm2020包括JDK部分的教程详解
Sep 17 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实现小型站点广告管理
2006/10/09 PHP
php上传图片类及用法示例
2016/05/11 PHP
Laravel中unique和exists验证规则的优化详解
2018/01/28 PHP
[原创]IE view-source 无法查看看源码 JavaScript看网页源码
2009/07/19 Javascript
jquery select选中的一个小问题
2009/10/11 Javascript
预加载css或javascript的js代码
2010/04/23 Javascript
javascript十六进制及二进制转化的方法
2015/05/06 Javascript
jquery带下拉菜单和焦点图代码分享
2015/08/24 Javascript
使用RequireJS库加载JavaScript模块的实例教程
2016/06/06 Javascript
一个简单不报错的summernote 图片上传案例
2016/07/11 Javascript
AngularJS基础 ng-mouseenter 指令示例代码
2016/08/02 Javascript
js注入 黑客之路必备!
2016/09/14 Javascript
Bootstrap 过渡效果Transition 模态框(Modal)
2017/03/17 Javascript
javascript闭包功能与用法实例分析
2017/04/06 Javascript
关于Google发布的JavaScript代码规范你要知道哪些
2018/04/04 Javascript
让axios发送表单请求形式的键值对post数据的实例
2018/08/11 Javascript
微信小程序如何获取手机验证码
2018/11/04 Javascript
如何解决.vue文件url引用文件的问题
2019/01/18 Javascript
jQuery移动端跑马灯抽奖特效升级版(抽奖概率固定)实现方法
2019/01/18 jQuery
[01:46]新英雄登场
2019/09/10 DOTA
[08:56]DOTA2-DPC中国联赛2月23日Recap集锦
2021/03/11 DOTA
wxPython 入门教程
2008/10/07 Python
Python with用法实例
2015/04/14 Python
利用python将json数据转换为csv格式的方法
2018/03/22 Python
python将处理好的图像保存到指定目录下的方法
2019/01/10 Python
django fernet fields字段加密实践详解
2019/08/12 Python
TFRecord文件查看包含的所有Features代码
2020/02/17 Python
基于python实现数组格式参数加密计算
2020/04/21 Python
学python需要去培训机构吗
2020/07/01 Python
巧用CSS3的calc()宽度计算做响应模式布局的方法
2018/03/22 HTML / CSS
阿姆斯特丹城市卡:Amsterdam Pass
2019/12/01 全球购物
可以使用抽象函数重写基类中的虚函数吗
2013/06/02 面试题
入党自荐书范文
2014/03/09 职场文书
写给老师的保证书
2015/05/09 职场文书
繁星春水读书笔记
2015/06/30 职场文书
Python 图片添加美颜效果
2022/04/28 Python