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 相关文章推荐
PHP中比较两个字符串找出第一个不同字符位置例子
Apr 08 PHP
php实例分享之mysql数据备份
May 19 PHP
PHP实现删除非站内外部链接实例代码
Jun 17 PHP
php使用fgetcsv读取csv文件出现乱码的解决方法
Nov 08 PHP
php实现用手机关闭计算机(电脑)的方法
Apr 22 PHP
PHP简单实现文本计数器的方法
Apr 28 PHP
Yii CGridView用法实例详解
Jul 12 PHP
PHP利用超级全局变量$_GET来接收表单数据的实例
Nov 05 PHP
php使用gd2绘制基本图形示例(直线、圆、正方形)
Feb 15 PHP
windows环境下使用Composer安装ThinkPHP5
May 18 PHP
php和redis实现秒杀活动的流程
Jul 17 PHP
laravel orm 关联条件查询代码
Oct 21 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
php下安装配置fckeditor编辑器的方法
2011/03/02 PHP
PHP版网站缓存加快打开速度的方法分享
2012/06/03 PHP
分享一下贝贝成长进度的php代码
2012/09/14 PHP
thinkPHP删除前弹出确认框的简单实现方法
2016/05/16 PHP
js实现图片放大缩小功能后进行复杂排序的方法
2012/11/08 Javascript
JavaScript实现的一个日期格式化函数分享
2014/12/06 Javascript
Javascript基础_嵌入图像的简单实现
2016/06/14 Javascript
BootstrapValidator超详细教程(推荐)
2016/12/07 Javascript
用js将long型数据转换成date型或datetime型的实例
2017/07/03 Javascript
react开发教程之React 组件之间的通信方式
2017/08/12 Javascript
vue-lazyload图片延迟加载插件的实例讲解
2018/02/09 Javascript
vue.js的computed,filter,get,set的用法及区别详解
2018/03/08 Javascript
使用jquery DataTable和ajax向页面显示数据列表的方法
2018/08/09 jQuery
NodeJs 文件系统操作模块fs使用方法详解
2018/11/26 NodeJs
Vue动态生成表格的行和列
2019/07/18 Javascript
原生js实现html手机端城市列表索引选择城市
2020/06/24 Javascript
vue实现几秒后跳转新页面代码
2020/09/09 Javascript
基于javascript实现移动端轮播图效果
2020/12/21 Javascript
Python读取一个目录下所有目录和文件的方法
2016/07/15 Python
python读写json文件的简单实现
2017/04/11 Python
python爬虫爬取快手视频多线程下载功能
2018/02/28 Python
在matplotlib的图中设置中文标签的方法
2018/12/13 Python
Python list列表中删除多个重复元素操作示例
2019/02/27 Python
python之yield和Generator深入解析
2019/09/18 Python
Pytorch使用MNIST数据集实现基础GAN和DCGAN详解
2020/01/10 Python
使用python客户端访问impala的操作方式
2020/03/28 Python
Python 读取位于包中的数据文件
2020/08/07 Python
全球速卖通西班牙站:AliExpress西班牙
2017/10/30 全球购物
自然健康的概念:Natural Healthy Concepts
2020/01/26 全球购物
新西兰最大的天然保健及护肤品网站:HealthPost(直邮中国)
2021/02/13 全球购物
公司同意接收函
2014/01/13 职场文书
自愿离婚协议书2015
2015/01/26 职场文书
关于教师节的广播稿
2015/08/19 职场文书
电工生产实习心得体会
2016/01/22 职场文书
《所见》教学反思
2016/02/23 职场文书
Android移动应用开发指南之六种布局详解
2022/09/23 Java/Android