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原創文章
相關文章
相關標籤/搜索