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 相关文章推荐
15种PHP Encoder的比较
Apr 17 PHP
PHP 分页类(模仿google)-面试题目解答
Sep 13 PHP
PHP中的MYSQL常用函数(php下操作数据库必备)
Sep 12 PHP
8个PHP程序员常用的功能汇总
Dec 18 PHP
php程序总是提示验证码输入有误解决方案
Jan 07 PHP
PHP 常用的header头部定义汇总
Jun 19 PHP
启用Csrf后POST数据时出现的400错误
Jul 05 PHP
yii2整合百度编辑器umeditor及umeditor图片上传问题的解决办法
Apr 20 PHP
php简单备份与还原MySql的方法
May 09 PHP
PHP的openssl加密扩展使用小结(推荐)
Jul 18 PHP
php表单文件iframe异步上传实例讲解
Jul 26 PHP
PHP中一个有趣的preg_replace函数详解
Aug 15 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 array_merge下进行数组合并的代码
2008/07/22 PHP
yiic命令时提示“php.exe”不是内部或外部命令的解决方法
2014/12/18 PHP
PHP获取数组最后一个值的2种方法
2015/01/21 PHP
分享php邮件管理器源码
2016/01/06 PHP
php array_values 返回数组的所有值详解及实例
2016/11/12 PHP
PHP连接MySQL进行增、删、改、查操作
2017/02/19 PHP
PHP goto语句用法实例
2019/08/06 PHP
javascript 获取select下拉列表值的代码
2009/09/07 Javascript
JQuery中DOM加载与事件执行实例分析
2015/06/13 Javascript
JS 日期与时间戮相互转化的简单实例
2016/06/22 Javascript
js实现多行文本框统计剩余字数功能
2017/03/28 Javascript
bing Map 在vue项目中的使用详解
2018/04/09 Javascript
JavaScript callback回调函数用法实例分析
2018/05/08 Javascript
webpack4 + react 搭建多页面应用示例
2018/08/03 Javascript
详解微信小程序canvas圆角矩形的绘制的方法
2018/08/22 Javascript
node.js Promise对象的使用方法实例分析
2019/12/26 Javascript
Vue 实现登录界面验证码功能
2020/01/03 Javascript
JavaScript enum枚举类型定义及使用方法
2020/05/15 Javascript
[02:57]DOTA2英雄基础教程 风行者
2014/01/16 DOTA
Python 代码性能优化技巧分享
2012/08/07 Python
python基础教程之udp端口扫描
2014/02/10 Python
Python获取网页上图片下载地址的方法
2015/03/11 Python
用于统计项目中代码总行数的Python脚本分享
2015/04/21 Python
Python3编码问题 Unicode utf-8 bytes互转方法
2018/10/26 Python
Python数据可视化教程之Matplotlib实现各种图表实例
2019/01/13 Python
Python画图实现同一结点多个柱状图的示例
2019/07/07 Python
python 发送json数据操作实例分析
2019/10/15 Python
python读取csv文件指定行的2种方法详解
2020/02/13 Python
如何使用Django Admin管理后台导入CSV
2020/11/06 Python
菲律宾酒店预订网站:Hotels.com菲律宾
2017/07/12 全球购物
美国球鞋寄卖网站:Stadium Goods
2018/05/09 全球购物
美国农场商店:Blain’s Farm & Fleet
2020/01/17 全球购物
党支部公开承诺践诺书
2014/03/28 职场文书
我的中国心演讲稿
2014/09/04 职场文书
兴趣班停课通知
2015/04/24 职场文书
MySQL约束超详解
2021/09/04 MySQL