yii2中关于加密解密的那些事儿


Posted in PHP onJune 12, 2018

前言

Yii提供了方便的帮助函数来让你用一个安全秘钥来加密解密数据。数据通过加密函数进行传输,这样只有拥有安全秘钥的人才能解密。比如,我们需要存储一些信息到我们的数据库中,但是,我们需要保证只有拥有安全秘钥的人才能看到它(即使应用的数据库泄露)。

大家也都知道,我们做程序的时候,加密解密是绕不开的话题,使用yii2开发应用的时候,都内置了哪些有关加密解密(安全)方便的支持那?本文将为你揭晓。

相关环境

  • 操作系统及IDE macOS 10.13.1 & PhpStorm2018.1.2
  • 软件版本 PHP7.1.8 Yii2.0.14

在yii2中,管理加密解密的库叫做Security,它以yii2组件的形式存在,因此你可以通过Yii::$app->security来获取并使用它。

Security组件源代码位置如下

vendor/yiisoft/yii2/base/Security.php

Security组件一共有15个与加密解密(&编码)相关的公共方法,我们先来列一个清单。

  • encryptByPassword
  • encryptByKey
  • decryptByPassword
  • decryptByKey
  • hkdf
  • pbkdf2
  • hashData
  • validateData
  • generateRandomKey
  • generateRandomString
  • generatePasswordHash
  • validatePassword
  • compareString
  • maskToken
  • unmaskToken

我想有一些你一定没见过,没关系,我们一一去了解。

generateRandomString

之所以先说generateRandomString是因为它最常用,起码我是这样。

public function generateRandomString($length = 32){...}

生成一个随机的字符串,参数$length代表这个字符串的长度,默认32位。值得说明的是这个字符串的取值为范围是[A-Za-z0-9_-]。

generatePasswordHash & validatePassword

generatePasswordHash & validatePassword经常被用来加密用户密码以及对密码是否正确的验证,自从MD5可能被碰撞后,我们用yii2开发应用的时候,generatePasswordHash函数对密码进行加密就成为首选了,它调用了crypt函数。

一般用法如下

// 使用generatePasswordHash为用户的密码加密,$hash存储到库中
$hash = Yii::$app->getSecurity()->generatePasswordHash($password);

// 使用validatePassword对密码进行验证
if(Yii::$app->getSecurity()->validatePassword($password, $hash)){
 // 密码正确
}else{
 // 密码错误
}

generateRandomKey

和generateRandomString类似,生成一个随机的串,参数为长度,默认为32位,区别在于generateRandomKey生成的不是ASCII。

简单的说 generateRandomString 约等于 base64_encode(generateRandomKey)。

encryptByPassword & decryptByPassword

编码和解码函数,使用一个秘钥对数据进行编码,然后通过此秘钥在对编码后的数据进行解码。

例子

$dat = Yii::$app->security->encryptByPassword("hello","3166886");
echo Yii::$app->security->encryptByPassword($dat,"3166886");// hello

要注意,通过上面得到的编码后的数据不是ASCII,可以通过base64_encode和base64_decode在外层包装下。

encryptByKey & decryptByKey

同样是一组编码和解码函数,比通过密码的方式要快。函数声明为

public function encryptByKey($data, $inputKey, $info = null){}

public function decryptByKey($data, $inputKey, $info = null){}

encryptByKey & decryptByKey 存在着第三个参数,比如我们可以传递会员的ID等,这样此信息将和$inputKey一起作为加密解密的钥匙。

hkdf

使用标准的 HKDF 算法从给定的输入键中导出一个键。在PHP7+使用的是hash_hkdf方法,小于PHP7使用hash_hmac方法。

pbkdf2

使用标准的 PBKDF2 算法从给定的密码导出一个密钥。该方法可以用来进行密码加密,不过yii2有更好的密码加密方案 generatePasswordHash。

hashData和validateData

有的时候为了防止内容被篡改,我们需要对数据进行一些标记,hashData和validateData就是完成这个任务的组合。

hashData 用来对原始数据进行加数据前缀,比如如下代码

$result = Yii::$app->security->hashData("hello",'123456',false);
// ac28d602c767424d0c809edebf73828bed5ce99ce1556f4df8e223faeec60eddhello

你看到了在hello的前面多了一组字符,这组字符会随着原始数据的不同而变化。这样我们就对数据进行了特殊的防止篡改标记,接下来是validateData上场了。

注意:hashData的第三个参数代表生成的哈希值是否为原始二进制格式. 如果为false, 则会生成小写十六进制数字.

validateData 对已经加了数据前缀的数据进行检测,如下代码

$result = Yii::$app->security->validateData("ac28d602c767424d0c809edebf73828bed5ce99ce1556f4df8e223faeec60eddhello",'123456',false);
// hello

如果返回了原始的字符串则表示验证通过,否则会返回假。

validateData 函数的第三个参数应该与使用  hashData() 生成数据时的值相同. 它指示数据中的散列值是否是二进制格式. 如果为false, 则表示散列值仅由小写十六进制数字组成. 将生成十六进制数字.

compareString

可防止时序攻击的字符串比较,用法非常简单。

Yii::$app->security->compareString("abc",'abc');

结果为真则相等,否则不相等。

那么什么是时序攻击那?我来举一个简单的例子。

if($code == Yii::$app->request->get('code')){
 
}

上面的比较逻辑,两个字符串是从第一位开始逐一进行比较的,发现不同就立即返回 false,那么通过计算返回的速度就知道了大概是哪一位开始不同的,这样就实现了电影中经常出现的按位破解密码的场景。

而使用 compareString 比较两个字符串,无论字符串是否相等,函数的时间消耗是恒定的,这样可以有效的防止时序攻击。

maskToken && unmaskToken

maskToken用于掩盖真实token且不可以压缩,同一个token最后生成了不同的随机令牌,在yii2的csrf功能上就使用了maskToken,原理并不复杂,我们看下源码。

public function maskToken($token){
 $mask = $this->generateRandomKey(StringHelper::byteLength($token));
 return StringHelper::base64UrlEncode($mask . ($mask ^ $token));
}

而unmaskToken目的也很明确,用于得到被maskToken掩盖的token。

接下来我们看一个例子代码

$token = Yii::$app->security->maskToken("123456");
echo Yii::$app->security->unmaskToken($token);// 结果为 123456

最后我们总结下

  • 加密/解密: encryptByKey()、decryptByKey()、 encryptByPassword() 和 decryptByPassword();
  • 使用标准算法的密钥推导: pbkdf2() 和 hkdf();
  • 防止数据篡改: hashData() 和 validateData();
  • 密码验证: generatePasswordHash() 和 validatePassword()

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
基于mysql的bbs设计(三)
Oct 09 PHP
PHP中的日期及时间
Nov 23 PHP
php smarty的预保留变量总结
Dec 04 PHP
PHP 事务处理数据实现代码
May 13 PHP
php编写一个简单的路由类
Apr 13 PHP
php小型企业库存管理系统的设计与实现代码
May 16 PHP
基于PHP异步执行的常用方式详解
Jun 03 PHP
ThinkPHP中I(),U(),$this->post()等函数用法
Nov 22 PHP
PHP安装memcached扩展笔记
May 28 PHP
php模仿qq空间或朋友圈发布动态、评论动态、回复评论、删除动态或评论的功能(中)
Jun 11 PHP
启用OPCache提高PHP程序性能的方法
Mar 21 PHP
Laravel Eloquent分表方法并使用模型关联的实现
Nov 25 PHP
php中curl和soap方式请求服务超时问题的解决
Jun 11 #PHP
Laravel框架模板继承操作示例
Jun 11 #PHP
Laravel框架模板加载,分配变量及简单路由功能示例
Jun 11 #PHP
Laravel框架在本地虚拟机快速安装的方法详解
Jun 11 #PHP
thinkPHP5框架中widget的功能与用法详解
Jun 11 #PHP
thinkPHP5框架自定义验证器实现方法分析
Jun 11 #PHP
PHP绕过open_basedir限制操作文件的方法
Jun 10 #PHP
You might like
Windows IIS PHP 5.2 安装与配置方法
2009/06/08 PHP
浅析PHP substr,mb_substr以及mb_strcut的区别和用法
2013/06/21 PHP
php/js获取客户端mac地址的实现代码
2013/07/08 PHP
强制PHP命令行脚本单进程运行的方法
2014/04/15 PHP
CI框架表单验证实例详解
2016/11/21 PHP
php PDO判断连接是否可用的实现方法
2017/04/03 PHP
获取任意Html元素与body之间的偏移距离 offsetTop、offsetLeft (For:IE5+ FF1 )[
2006/12/22 Javascript
让人期待的2011年度最佳 jQuery 插件分享
2012/03/16 Javascript
javascript中兼容主流浏览器的动态生成iframe方法
2014/05/05 Javascript
Web前端开发工具——bower依赖包管理工具
2016/03/29 Javascript
Vuejs第十二篇之动态组件全面解析
2016/09/09 Javascript
Jquery表单验证失败后不提交的解决方法
2016/10/18 Javascript
jQuery插件ContextMenu自定义图标
2017/03/15 Javascript
ES6新特性八:async函数用法实例详解
2017/04/21 Javascript
Node.js成为Web应用开发最佳选择的原因
2018/02/05 Javascript
react-native-video实现视频全屏播放的方法
2018/03/19 Javascript
Vue 页面切换效果之 BubbleTransition(推荐)
2018/04/08 Javascript
Vue项目中使用better-scroll实现一个轮播图自动播放功能
2018/12/03 Javascript
微信小程序实现圆形进度条动画
2020/11/18 Javascript
Python脚本实现网卡流量监控
2015/02/14 Python
python实现nao机器人手臂动作控制
2019/04/29 Python
python 生成器和迭代器的原理解析
2019/10/12 Python
使用IPython或Spyder将省略号表示的内容完整输出
2020/04/20 Python
pytorch查看通道数 维数 尺寸大小方式
2020/05/26 Python
一波HTML5 Canvas基础绘图实例代码集合
2016/02/28 HTML / CSS
全球速卖通巴西站点:Aliexpress巴西
2016/08/24 全球购物
韩国美国时尚服装和美容在线全球市场:KOODING
2018/11/07 全球购物
Fossil德国官网:化石手表、手袋、珠宝及配件
2019/12/07 全球购物
PHP面试题-$message和$$message的区别
2015/12/08 面试题
机关领导干部作风整顿整改措施
2014/09/19 职场文书
个人委托书如何写
2014/09/25 职场文书
2015年初中元旦晚会活动总结
2014/11/28 职场文书
迟到检讨书范文
2015/01/27 职场文书
2015婚礼主持词开场白
2015/05/28 职场文书
Win11如何修改dns?Win11修改dns图文教程
2022/01/18 数码科技
Spring Boot项目传参校验的最佳实践指南
2022/04/05 Java/Android