很高興能在專案中使用到RSA,AES128,以及MD5,用以保證客戶端(Client)和服務端(Server)之間的通訊安全。接下來會盡力的描述清楚關於本次使用的流程。具體關於演算法的細節,自行Wiki。
原來只是對加密這一塊很簡單的瞭解,比如只知道一些對稱加密,非對稱加密,md5單向加密等。通過本次的學習,很驚豔於可以將多種加密方式那麼完美的結合到一起。讓整個通訊過程變得如此美妙。雖然增加了服務端和客戶端的工作量,但是保證資料的一致出口,一致入口,只需要在出口和入口處加上邏輯,就可以很好的避免擾亂原有邏輯的煩惱。
簡單的概念,文章可能會涉及到
- RSA——非對稱加密,會產生公鑰和私鑰,公鑰在客戶端,私鑰在服務端。公鑰用於加密,私鑰用於解密。
- AES——對稱加密,直接使用給定的祕鑰加密,使用給定的祕鑰解密。(加密解密使用相同的祕鑰)
- MD5——一種被廣泛使用的密碼雜湊函式,可以產生出一個128位(16位元組)的雜湊值(hash value)
- Base64編碼——對位元組陣列轉換成字串的一種編碼方式
客戶端,服務端的通訊邏輯
之前:明文傳輸通訊
- 客戶端將要上傳的資料以字典(Map)的方式打包,Post提交給伺服器。
- 伺服器接收提交的資料包,通過Key-Value的形式獲取客戶端提交的值,進行處理。
- 處理結束,將資料以字典(Map)的形式打包,返回給客戶端處理。
加密傳輸通訊
整個流程是:
客戶端上傳資料加密 ==> 伺服器獲取資料解密 ==> 伺服器返回資料加密 ==> 客戶端獲取資料解密
-
客戶端上傳資料加密 A
- 客戶端隨機產生一個16位的字串,用以之後AES加密的祕鑰,AESKey。
- 使用RSA對AESKey進行公鑰加密,RSAKey
- (此處某些重要的介面需要加簽處理,後續講解,不要加簽處理的省略該步驟)
- 將明文的要上傳的資料包(字典/Map)轉為Json字串,使用AESKey加密,得到JsonAESEncryptedData。
- 封裝為{key : RSAKey, value : JsonAESEncryptedData}的字典上傳伺服器,伺服器只需要通過key和value,然後解析,獲取資料即可。
-
伺服器獲取資料解密 B
- 獲取到RSAKey後用伺服器私鑰解密,獲取到AESKey
- 獲取到JsonAESEncriptedData,使用AESKey解密,得到明文的客戶端上傳上來的資料。
- (如果客戶端進行了加簽處理,此處需要驗籤,以保證資料在網路傳輸過程中是否被篡改)
-
伺服器返回資料加密 C
- 將要返回給客戶端的資料(字典/Map)轉成Json字串,用AESKey加密處理
- (此處也可以加簽處理)
- 封裝資料{data : value}的形式返回給客戶端
-
客戶端獲取資料解密 D
- 客戶端獲取到資料後通過key為data得到伺服器返回的已經加密的資料AESEncryptedResponseData
- 對AESEncryptedResponseData使用AESKey進行解密,得到明文伺服器返回的資料。
加簽和驗籤
第二節——**"客戶端,服務端的通訊邏輯"已經基本上把客戶端和服務端的通訊加密邏輯講完了。至於"加簽和驗籤"**主要是針對資料傳輸過程中,防止資料被篡改的一種做法。
資料被篡改,栗子:
對於一個運動型別的APP,上傳運動的步數,是一個常見的介面操作。比如該介面會有幾個欄位,step(步數),time(步數產生的時間),memberId(使用者id)。
假設某使用者抓取了你上傳的資料包,然後成功的破解了你之前的加密方式。得到對應的明文,此時該使用者就可以隨意修改你的資料,比如step,然後以相同的方式加密,post到你的伺服器,此時伺服器會認為這是一次正常的請求,便接受了這個修改後的步數。其實此時的資料是錯誤的。如此神不知鬼不覺。。。
為了防止這種做法,我們可以是加簽的處理方式
-
加簽處理(資料發起方都可以加簽,此處是客戶端)
- 我們一般取其中的關鍵欄位(別人可能修改的欄位),比如此時step,和time及memberId,都比較敏感。
- 在上文的A中的第二步之後,獲取step,time,memberId,拼接成一個字串(順序和伺服器約定好),然後使用md5,採用base64編碼(編碼格式和服務約定)。得到signData
- 然後將獲取到的signData以key-value的形式儲存到原來明文的資料包中,然後進行A的第三步
-
驗籤處理(資料接受方都可以驗籤,此處服務端)
- 如上,到B的第三步,此時已經得到了客戶端上傳的明文資料
- 按照喝客戶端約定的欄位拼接,將得到的step,time,memberId拼接後,使用同樣的md5_base64處理,然後比較資料包中的簽名sign是否和客戶端當時的簽名一致。
- 如果一致,接受資料。不一致,拋棄資料,終止本次操作
假設加簽之後的資料包被截獲,然後解密成功,得到明文的資料包。但是簽名md5加密是無法解密的(單向加密)。此時即時修改了step,然後post到伺服器,伺服器通過修改後的step,time,memberId得到的字串經過md5加密後,一定會與客戶端的簽名不一致。從而資料被拋棄。
流程圖描述上文
示例程式碼
關於AES,和RSA加密解密,只能出iOS端的程式碼。關於如何在Linux下生成RSA公鑰和私鑰證書,參照RSA公鑰、私鑰生成,詳細講解,網上很多
執行,如下入顯示
RSA公鑰-生成自簽名證書
// 生成1024位私鑰
openssl genrsa -out private_key.pem 1024
// 根據私鑰生成CSR檔案
openssl req -new -key private_key.pem -out rsaCertReq.csr
// 根據私鑰和CSR檔案生成crt檔案
openssl x509 -req -days 3650 -in rsaCertReq.csr -signkey private_key.pem -out rsaCert.crt
// 為IOS端生成公鑰der檔案
openssl x509 -outform der -in rsaCert.crt -out public_key.der
// 將私鑰匯出為這p12檔案
openssl pkcs12 -export -out private_key.p12 -inkey private_key.pem -in rsaCert.crt
複製程式碼
參照 漫談RSA非對稱加密解密
推薦工具
-
關於畫流程圖
之前一致比較苦擾在Mac上有哪一款好用的可以畫流程圖,UML的工具,甚至都考慮過Keynote。最後發現這款線上的工具很不錯,上圖就是使用這款工具,第一次畫的。效果不錯。就是匯出png圖片解析度不是很好
-
關於AES加密解密線上工具