結合RSA,AES128,MD5---移動端與服務端在通訊層的加密處理的一次實驗

Swiftly發表於2018-03-16

很高興能在專案中使用到RSA,AES128,以及MD5,用以保證客戶端(Client)和服務端(Server)之間的通訊安全。接下來會盡力的描述清楚關於本次使用的流程。具體關於演算法的細節,自行Wiki。

原來只是對加密這一塊很簡單的瞭解,比如只知道一些對稱加密,非對稱加密,md5單向加密等。通過本次的學習,很驚豔於可以將多種加密方式那麼完美的結合到一起。讓整個通訊過程變得如此美妙。雖然增加了服務端和客戶端的工作量,但是保證資料的一致出口,一致入口,只需要在出口和入口處加上邏輯,就可以很好的避免擾亂原有邏輯的煩惱。

簡單的概念,文章可能會涉及到

  1. RSA——非對稱加密,會產生公鑰和私鑰,公鑰在客戶端,私鑰在服務端。公鑰用於加密,私鑰用於解密。
  2. AES——對稱加密,直接使用給定的祕鑰加密,使用給定的祕鑰解密。(加密解密使用相同的祕鑰)
  3. MD5——一種被廣泛使用的密碼雜湊函式,可以產生出一個128位(16位元組)的雜湊值(hash value)
  4. Base64編碼——對位元組陣列轉換成字串的一種編碼方式

客戶端,服務端的通訊邏輯

之前:明文傳輸通訊

  1. 客戶端將要上傳的資料以字典(Map)的方式打包,Post提交給伺服器。
  2. 伺服器接收提交的資料包,通過Key-Value的形式獲取客戶端提交的值,進行處理。
  3. 處理結束,將資料以字典(Map)的形式打包,返回給客戶端處理。

加密傳輸通訊

整個流程是:

客戶端上傳資料加密 ==> 伺服器獲取資料解密 ==> 伺服器返回資料加密 ==> 客戶端獲取資料解密

  • 客戶端上傳資料加密 A

    1. 客戶端隨機產生一個16位的字串,用以之後AES加密的祕鑰,AESKey。
    2. 使用RSA對AESKey進行公鑰加密,RSAKey
    3. (此處某些重要的介面需要加簽處理,後續講解,不要加簽處理的省略該步驟)
    4. 將明文的要上傳的資料包(字典/Map)轉為Json字串,使用AESKey加密,得到JsonAESEncryptedData。
    5. 封裝為{key : RSAKey, value : JsonAESEncryptedData}的字典上傳伺服器,伺服器只需要通過key和value,然後解析,獲取資料即可。
  • 伺服器獲取資料解密 B

    1. 獲取到RSAKey後用伺服器私鑰解密,獲取到AESKey
    2. 獲取到JsonAESEncriptedData,使用AESKey解密,得到明文的客戶端上傳上來的資料。
    3. (如果客戶端進行了加簽處理,此處需要驗籤,以保證資料在網路傳輸過程中是否被篡改)
  • 伺服器返回資料加密 C

    1. 將要返回給客戶端的資料(字典/Map)轉成Json字串,用AESKey加密處理
    2. (此處也可以加簽處理)
    3. 封裝資料{data : value}的形式返回給客戶端
  • 客戶端獲取資料解密 D

    1. 客戶端獲取到資料後通過key為data得到伺服器返回的已經加密的資料AESEncryptedResponseData
    2. 對AESEncryptedResponseData使用AESKey進行解密,得到明文伺服器返回的資料。

加簽和驗籤

第二節——**"客戶端,服務端的通訊邏輯"已經基本上把客戶端和服務端的通訊加密邏輯講完了。至於"加簽和驗籤"**主要是針對資料傳輸過程中,防止資料被篡改的一種做法。

資料被篡改,栗子:

對於一個運動型別的APP,上傳運動的步數,是一個常見的介面操作。比如該介面會有幾個欄位,step(步數),time(步數產生的時間),memberId(使用者id)。

假設某使用者抓取了你上傳的資料包,然後成功的破解了你之前的加密方式。得到對應的明文,此時該使用者就可以隨意修改你的資料,比如step,然後以相同的方式加密,post到你的伺服器,此時伺服器會認為這是一次正常的請求,便接受了這個修改後的步數。其實此時的資料是錯誤的。如此神不知鬼不覺。。。

為了防止這種做法,我們可以是加簽的處理方式

  • 加簽處理(資料發起方都可以加簽,此處是客戶端)

    1. 我們一般取其中的關鍵欄位(別人可能修改的欄位),比如此時step,和time及memberId,都比較敏感。
    2. 在上文的A中的第二步之後,獲取step,time,memberId,拼接成一個字串(順序和伺服器約定好),然後使用md5,採用base64編碼(編碼格式和服務約定)。得到signData
    3. 然後將獲取到的signData以key-value的形式儲存到原來明文的資料包中,然後進行A的第三步
  • 驗籤處理(資料接受方都可以驗籤,此處服務端)

    1. 如上,到B的第三步,此時已經得到了客戶端上傳的明文資料
    2. 按照喝客戶端約定的欄位拼接,將得到的step,time,memberId拼接後,使用同樣的md5_base64處理,然後比較資料包中的簽名sign是否和客戶端當時的簽名一致。
    3. 如果一致,接受資料。不一致,拋棄資料,終止本次操作

假設加簽之後的資料包被截獲,然後解密成功,得到明文的資料包。但是簽名md5加密是無法解密的(單向加密)。此時即時修改了step,然後post到伺服器,伺服器通過修改後的step,time,memberId得到的字串經過md5加密後,一定會與客戶端的簽名不一致。從而資料被拋棄。

流程圖描述上文

客戶端服務端通訊加密邏輯.png

示例程式碼

關於AES,和RSA加密解密,只能出iOS端的程式碼。關於如何在Linux下生成RSA公鑰和私鑰證書,參照RSA公鑰、私鑰生成,詳細講解,網上很多

github的demo地址--CAAdvancedTech

執行,如下入顯示

首頁選擇加密模組

AES,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非對稱加密解密

推薦工具

  1. 關於畫流程圖

    之前一致比較苦擾在Mac上有哪一款好用的可以畫流程圖,UML的工具,甚至都考慮過Keynote。最後發現這款線上的工具很不錯,上圖就是使用這款工具,第一次畫的。效果不錯。就是匯出png圖片解析度不是很好

    工具processOn

    Mac 上最好用的流程圖軟體是什麼?

  2. 關於AES加密解密線上工具

    線上AES加解密

相關文章