yii2的加密解密那些事儿

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

相关环境php

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

在yii2中,管理加密解密的库叫作Security,它以yii2组件的形式存在,所以你能够经过Yii::$app->security来获取并使用它。html

Security组件源代码位置以下算法

vendor/yiisoft/yii2/base/Security.php

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

  1. encryptByPassword
  2. encryptByKey
  3. decryptByPassword
  4. decryptByKey
  5. hkdf
  6. pbkdf2
  7. hashData
  8. validateData
  9. generateRandomKey
  10. generateRandomString
  11. generatePasswordHash
  12. validatePassword
  13. compareString
  14. maskToken
  15. unmaskToken

我想有一些你必定没见过,不要紧,咱们一一去了解。yii2

generateRandomString

之因此先说generateRandomString是由于它最经常使用,起码我是这样。app

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

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

generatePasswordHash & validatePassword

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

通常用法以下函数

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

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

generateRandomKey

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

简单的说 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()
更多Yii原创文章
相关文章
相关标签/搜索