##1.26.1 對稱加密和非對稱加密
關于數據加密和安全這一塊,只作簡單說明。
首先,對稱加密是指數據可以加密成密文也可以解密還原,共用同一個密鑰,而非對稱是則公鑰和私鑰,兩者皆使用可逆加密算法。不可逆加密不存在密鑰,只有salt,用來增加可變性和隨機性,如md5。而在加密里面,又數塊算法加密的方式最為完善,隨附圖一張:

##1.26.2 PHP的mcrypt加密擴展
在PhalApi中,同樣也是使用了mcrypt作為底層的數據加密技術方案。請查看: [PHP 手冊 函數參考 加密擴展](http://php.net/manual/zh/book.mcrypt.php)
##1.26.3 加解密的使用
在單元測試中,我們可以快速找到加密和解密的使用,這里再簡單舉一例:
```javascript
$mcrypt = new PhalApi_Crypt_Mcrypt('12345678');
$data = 'The Best Day of My Life';
$key = 'phalapi';
$encryptData = $mcrypt->encrypt($data, $key);
var_dump($encryptData);
$decryptData = $mcrypt->decrypt($encryptData, $key);
var_dump($decryptData);
```
上面將會輸出(有亂碼):

##1.26.4 更富彈性和便于存儲的加密方案
上面看到,mcrypt下的加密在兩點不足:
+ 1、有亂碼,不能很好地永久化存儲;
+ 2、只針對文本字符串的加密,不支持數組等,且無法還原類型;
為此, 我們提供了更富彈性和便于存儲的加密方案,即:序列化 + base64 + mcrypt的多重加密方案。
以下是上面的示例-多重加密版:
```javascript
$mcrypt = new PhalApi_Crypt_MultiMcrypt('12345678');
$data = 'The Best Day of My Life';
$key = 'phalapi';
$encryptData = $mcrypt->encrypt($data, $key);
var_dump($encryptData);
$decryptData = $mcrypt->decrypt($encryptData, $key);
var_dump($decryptData);
```
對應的輸出(這里使用了文字結果輸出,是因為沒了亂碼):
```javascript
string(44) "rmFMdhvszAkHhOdzwt/APBACk/Mn/SqhV1Ahp1xT0Gk="
string(23) "The Best Day of My Life"
```
##1.26.5 RSA的支持與超長字符串的應對方案
基于項目有使用RSA進行加密和解密的需求,這里特擴展對RSA的支持。同時針對到RSA對字符串長度的限制,提供了分段處理的方案。RSA加密模塊的靜態類結構UML如下:

###(1)原生態的通信加密和解密
此部分只是簡單地封裝了openssl相關函數的操作,可以實現與其他語言和客戶端下RSA的加密通信。
唯一需要注意的是,對于 **“私鑰加密,公鑰解密”** 和 **“公鑰加密,私鑰解密”** 這兩種情況下key的互換和對應問題。不要混淆。
###(2)超長字符串的分段處理
這里重點說明一下超長字符串通信加密的問題。
解決方案主要涉及兩點:一是分段的處理,二是中間層轉換。分段是指將待加密的字符串分割成允許最大長度117(有用戶反饋說是127)內的數組,再各自處理;中間層轉換是為了穩定性、通用性和方便落地存儲,使用了json和base64的結合編碼。
雖然此方案解決了超長字符串的問題,但需要特別指出的是, **不能與其他語言、或者PHP其他框架和客戶端進行原生態的RSA通信** 。
我們突破了長度的限制,但失去了通用性。這里羅列一下各個場景和對應的處理方式:
####支持:PhalApi項目A <--> PhalApi項目A
####支持:PhalApi項目A <--> PhalApi項目B,PhalApi項目C,PhalApi項目D,...
####不支持:PhalApi項目 <--> 非PhalApi項目的PHP項目
解決方案:將以下RSA模塊相關的代碼以包的形式拷貝到需要的PHP項目。
```javascript
.
├── Crypt
│?? └── RSA
│?? ├── KeyGenerator.php
│?? ├── MultiBase.php
│?? ├── MultiPri2Pub.php
│?? ├── MultiPub2Pri.php
│?? ├── Pri2Pub.php
│?? └── Pub2Pri.php
└── Crypt.php
```
####不支持:PhalApi項目 <--> 非PHP語言的項目
解決方案:參考PhalApi對RSA超長字符串的處理,同步實現。
####不支持:PhalApi項目 <--> 客戶端(iOS/Android/Windows Phone, etc)
解決方案:參考PhalApi對RSA超長字符串的處理,同步實現。
###(3)使用示例:2塊2毛2和故事
這是一個有趣的故事,發生在我一個很好的朋友身上。
在去年暑假的時候,有位師妹通過幾層關系找到我朋友,想他幫她支付回家的火車票。本著“調試”(調戲)的精神,我朋友爽快地答應了并讓她把支付寶帳號發過來。然后,不一會,我朋友收到了一條有支付寶帳號的短信,立馬打了2.22元過去,并附言: **別問我是誰,請叫我雷鋒!** 后來證實師妹沒發來過短信,原來收到的那條是詐騙的短信。。。。你能想象得到騙子收到這2.22元和看到這條留言時的表情么,哈哈~~
以下測試代碼,以上面故事為背景,并演示了RSA的使用示例:
```javascript
public function testDecryptAfterEncrypt()
{
$keyG = new PhalApi_Crypt_RSA_KeyGenerator();
$privkey = $keyG->getPriKey();
$pubkey = $keyG->getPubKey();
DI()->crypt = new PhalApi_Crypt_RSA_MultiPri2Pub();
$data = 'AHA! I have $2.22 dollars!';
$encryptData = DI()->crypt->encrypt($data, $privkey);
$decryptData = DI()->crypt->decrypt($encryptData, $pubkey);
$this->assertEquals($data, $decryptData);
}
```
##1.26.6 建議
在上面的加密中,接口項目在開發時,需要自定義兩個值:加密向量和私鑰。
為了提高數據加密的安全度,建議:
+ 加密向量項目統一在./Config/app.php中配置;
+ 各模塊業務數據加密所用的Key則由各業務點自定義;
這樣,可以對不同的數據使用不同的加密私鑰,即使破解了某一個用戶的數據,也難以破解其他用戶的。
##1.26.7 擴展你的對稱加密
尤其對于加密方案和算法,我們在項目開發決策時,更應該優先考慮使用現在行業內成熟公認的加密方案和算法,而不是自己去從頭研發。
但如果你項目確實有此需要,或者需要在mcrypt的基礎上再作一些變通,也是可以很快地實現和注冊使用。
首先,請先實現下面的加密接口:
```javascript
// $vim ./PhalApi/PhalApi/Crypt.php
interface PhalApi_Crypt {
public function encrypt($data, $key);
public function decrypt($data, $key);
}
```
然后,重新注冊加密服務即可。
- 歡迎使用PhalApi!
- 接口,從簡單開始!
- [1.1]-下載與安裝
- [1.2]-創建一個自己的項目
- [1.3]-在線體驗
- [1.4]-文檔、幫助和官網
- [1.10]-對PhalApi框架的抉擇
- [1.11]-快速入門(backup)
- [1.12]-參數規則:接口參數規則配置
- [1.13]-統一的接口請求方式:_sevice=XXX.XXX
- [1.14]-統一的返回格式和結構:ret-data-msg
- [1.15]-數據庫操作:基于NotORM的使用及優化
- [1.16]-配置讀取:內外網環境配置的完美切換
- [1.17]-日記紀錄:簡化版的日記接口
- [1.18]-快速函數:人性化的關懷
- [1.19]-DI服務速查:各資源服務一覽表
- [1.20]-DB操作:數據庫基本操作速查
- [1.21]-類的自動加載:遵循PEAR包的命名規范
- [1.22]-簽名驗證:自定義簽名規則
- [1.23]-請求和響應:GET和POST兩者皆可得及超越JSON格式返回
- [1.24]-緩存策略:更靈活地可配置化的多級緩存
- [1.25]-國際化翻譯:為走向國際化提前做好翻譯準備
- [1.26]-數據安全:數據對稱加密方案
- [1.27]-精益開發:更富表現力的Model層和重量級數據獲取的應對方案
- [1.28]-COOKIE:對COOKIE原生態的支持及記憶加密升級版
- [1.29]-開放與封閉:多入口和統一初始化
- [1.30]-保持的力量:接口開發最佳實踐
- [1.31]-新型計劃任務:以接口形式實現的計劃任務
- [2.11]-核心思想:DI依賴注入-讓資源更可控
- [2.12]-海量數據:可配置的分庫分表
- [2.13]-接口調試:在線SQL語句查看與性能優化
- [2.14]-測試驅動開發:意圖導向編程下的接口開發
- [2.15]-演進:新型計劃任務續篇
- [2.16]-領域驅動設計:應對復雜領域業務的Domain層
- [2.17]-微服務:Api接口服務層
- [2.18]-定制化:資源服務的再實現
- [2.19]-擴展庫:可重用的擴展類庫
- [2.20]-約定編程:架構明顯的編程風格
- [2.21]-服務器統一部署方案簡明版:CentOs---Nginx---php-fpm---MySql-[--Memcached]
- [2.22]-更多工具:精益項目和團隊建設
- [3.1]-擴展類庫:微信開發
- [3.2]-擴展類庫:代理模式下phprpc協議的輕松支持
- [3.3]-擴展類庫:基于PHPMailer的郵件發送
- [3.4]-擴展類庫:優酷開放平臺接口調用
- [3.5]-擴展類庫:七牛云存儲接口調用
- [3.6]-擴展類庫:新型計劃任務
- [3.8]-擴展類庫:用戶、會話和第三方登錄集成
- [3.9]-擴展類庫:swoole支持下的長鏈接和異步任務實現
- [3.11]-擴展類庫:基于FastRoute的快速路由
- [4.2]-開發實戰2:模擬優酷開放平臺接口項目開發
- [4.3]-開發實戰3:一個簡單的小型項目開發(奔跑吧兄弟投票活動)
- [5.1]-架構與思想:PhalApi核心設計和思想解讀
- [5.2]-雜談:扯一些PhalApi的前世和今生
- [5.3]-框架總結:術語表和PHP開發建議
- [5.4]-許可
- [5.5]-聯系和加入我們
- [5.6]-更新日記
- [5.8]-致框架貢獻者:加入PhalApi開源指南
- [6.1]-基于接口查詢語言的SDK包
- [6.2]-SDK包(JAVA版)
- [6.3]-SDK包(PHP版)
- [6.4]-SDK包(Objective-C版)
- [6.5]-SDK包(javascript版)
- [6.6]-SDK包(Ruby版)
- [8.1]-PhalApi視頻教程
- 附錄1:接口文檔參考模板