Retrofit/OkHttp API接口加固技術實踐(下)

做者/Tamic
http://blog.csdn.net/sk719887916/article/details/65448628java

上節加固介紹了APi單純Post用對稱加密(Base64 爲列子)加密方式。這樣的加密方式仍是存在必定的風險,加密效率雖高,但易破解,本節將介紹怎麼用非對稱加密 來加解密okhttp的數據,本文採用RSA加密算法爲栗子。git

對稱加密

對稱加密是最傳統的加密方式,比上非對稱加密,缺乏安全性,但是它依然是用的比較多的加密方法。github


對稱加密採用單密鑰加密方式,不管是加密仍是解密都是用同一個密鑰,即「一把鑰匙開一把鎖」。對稱加密的優勢在於操做簡單、管理方便、速度快。它的缺點在於密鑰在
網絡傳輸中easy被竊聽,每個密鑰僅僅能應用一次。對密鑰管理形成了困難。對稱加密的實現形式和加密算法的公開性使它依賴於密鑰的安全性。而不是算法的安全性。算法

對稱加密原理以及對稱加密算法 瀏覽器

對稱加密的核心——通訊兩方共享一個密鑰 通訊過程: A有明文m,使用加密算法E,密鑰key。生成密文c=E(key,m); B收到密文c,使用解密算法D,密鑰key。獲得明文
m=D(key,c); 比喻: 對稱加密是最直觀,也是歷史最久遠的加密手段,類似於加鎖和解鎖,僅僅只是鑰匙的個數很是多(~~2^100)。一我的窮其一輩子也試不全然部可能的鑰匙
所以加密密鑰可以從解密密鑰中推算出來,同一時候解密密鑰也可以從加密密鑰中推算出來。安全

而在大多數的對稱算法中,加密密鑰和解密密鑰是一樣的。因此也稱這樣的加密算法爲祕
密密鑰算法或單密鑰算法。markdown

它要求發送方和接收方在安全通訊以前。商定一個密鑰。網絡

對稱算法的安全性依賴於密鑰,泄漏密鑰就意味着不論什麼人都可以對他們發送或接收的消息解
密,因此密鑰的保密性對通訊性相當重要。dom

主要有DES算法。3DES算法,TDEA算法,Blowfish算法。RC5算法。IDEA算法。ide

非對稱加密

非對稱密算法是一種密鑰的加密方法。

非對稱加密算法需要兩個密鑰:公鑰(publickey)和私鑰(privatekey)。公鑰與私鑰是一對存在,假設用公鑰對數據進行加密,僅僅實用相應的私鑰才幹解密;假設用密鑰對數據進行加密。那麼僅僅實用相應的公鑰才幹解密。因爲加密和解密使用的是兩個不一樣的密鑰,因此這樣的算法叫做非對稱加密算法。 非對稱加密算法實現機密信息交換的基本過程是:甲方生成一對密鑰並將當中的一把做爲公用密鑰向其餘方公開;獲得該公用密鑰的乙方使用該密鑰對機密信息進行加密後再發送給甲方;甲方再用本身保存的還有一把專用密鑰對加密後的信息進行解密。

還有一方面,甲方可以使用乙方的公鑰對機密信息進行簽名後再發送給乙方;乙方再用本身的私匙對數據進行驗籤。
甲方僅僅能用其專用密鑰解密由其公用密鑰加密後的不論什麼信息。 非對稱加密算法的保密性比較好,它消除了終於用戶交換密鑰的需要。


非對稱password體制的特色:算法強度複雜、安全性依賴於算法與密鑰但是因爲其算法複雜,而使得加密解密速度沒有對稱加密解密的速度快。對稱password體制中僅僅有一種密鑰,並且是非公開的,假設要解密就得讓對方知道密鑰。因此保證其安全性就是保證密鑰的安全,而非對稱密鑰體制有兩種密鑰,當中一個是公開的,這樣就可以不需要像對稱password那樣傳輸對方的密鑰了。這樣安全性就大了很是多。

列如 :支付寶的加密方式就採用非對稱加密方式。支付寶會給客戶提供支付寶證書,做爲用戶驗證是不是來自支付寶的數據。防止第三方假冒支付寶,而客戶手中持有私鑰。用戶支付寶發送的數據通過支付寶的公鑰進項加密,則支付寶可以採用本身的的私鑰進行解密。

工做過程

  • 1.A要向B發送信息,A和B都要產生一對用於加密
  • 2.A的私鑰保密,A的公鑰告訴B。B的私鑰保密。B的公鑰告訴A。

  • 3.A要給B發送信息時,A用B的公鑰加密信息。因爲A知道B的公鑰。
  • 4.A將這個數據發給B(已經用B的公鑰加密消息)。

  • 5.B收到這個數據後後,B用本身的私鑰解密A的消息。其餘所有收到這個報文的人都沒法解密,因爲僅僅有B纔有B的私鑰。

通俗點可以這麼理解:

  • 瀏覽器向server發出請求,詢問對方支持的對稱加密算法和非對稱加密算法;server迴應本身支持的算法。
  • 瀏覽器選擇兩方都支持的加密算法,並請求server出示本身的證書;server迴應本身的證書。
  • 瀏覽器隨機產生一個用於本次會話的對稱加密的鑰匙,並使用server證書中附帶的公鑰對該鑰匙進行加密後傳遞給server。server爲本次會話保持
  • 該對稱加密的鑰匙。第三方不知道server的私鑰,即便截獲了數據也沒法解密。非對稱加密讓不論什麼瀏覽器都可以與server進行加密會話。

瀏覽器使用對稱加密的鑰匙對請求消息加密後傳送給server,server使用該對稱加密的鑰匙進行解密;server使用對稱加密的鑰匙對響應消息加密後傳送給瀏覽器,瀏覽器使用該對稱加密的鑰匙進行解密。第三方不知道對稱加密的鑰匙,即便截獲了數據也沒法解密。對稱加密提升了加密速度

數字證書

數字證書就是互聯網通信中標誌通信各方身份信息的一串數字,提供了一種在Internet上驗證通訊實體身份的方式。數字證書不是數字身份證,而是身份認證機構蓋在數字身份證上的一個章或印(或者說加在數字身份證上的一個簽名)。

它是由權威機構——CA機構。又稱爲證書受權(Certificate Authority)中心發行的。人們可以在網上用它來識別對方的身份。


數字證書綁定了公鑰及其持有者的真實身份,它類似於現實生活中的居民身份證,所不一樣的是數字證書再也不是紙質的證照。而是一段含有證書持有者身份信息並通過認證中心審覈簽發的電子數據,普遍用在電子商務和移動互聯網中。。


通俗講就是車管所會給每個車輛進行認證頒發車牌。經過車牌咱們可以查到所有車輛和駕駛員的信,二數字證書就辨別惟一身份,支付寶等的數字證書就是公開的。這不是支付寶本身決定。而是由國際組織認證,這樣不管是哪一個用戶首先就可以依據瀏覽器返回的證書辨別支付寶的真僞。

數字簽名

數字簽名用來,保證信息傳輸的完整性、發送者的身份認證、防止交易中的抵賴發生。


數字簽名是將摘要信息用發送者的私鑰加密。與原文一塊兒傳送給接收者。接收者僅僅實用發送者的公鑰才幹解密被加密的摘要信息,而後用HASH函數對收到的原文產生一個摘要信息,與解密的摘要信息對照。假設一樣,則說明收到的信息是完整的,在傳輸過程當中沒有被改動,不然說明信息被改動過,所以數字簽名可以驗證信息的完整性。假設中途數據被纂改或者丟失。

那麼對方就可以依據數字簽名來辨別是不是來自對方的第一手信息數據。
數字簽名是個加密的過程,數字簽名驗證是個解密的過程。

參數加解密

首先。Android中生成了對稱密鑰:

public static  SecretKeySpec generateSymmetric() {

    // Set up secret key spec for 128-bit AES encryption and decryption
    SecretKeySpec sks = null;
    try {
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
        sr.setSeed("any data used as random seed".getBytes());
        KeyGenerator kg = KeyGenerator.getInstance("AES");
        kg.init(128, sr);
        sks = new SecretKeySpec((kg.generateKey()).getEncoded(), "AES");

        System.out.println("AES KEY: " + sks);
    } catch (Exception e) {
        Log.e(TAG, "AES secret key spec error");
    }
    return sks;
}

而後將SecretKeySpec轉換爲Base64字符串格式:

public static String ConvertSymmetricKeyToString(SecretKeySpec key) {

    String symmetric_key = null;

    symmetric_key = Base64.encodeToString(key.getEncoded(), Base64.DEFAULT);
    return symmetric_key;
}

調用函數:

 SecretKeySpec symmKey = generateSymmetric(); newSymmetricKeyString = CreateEncryptedXml.ConvertSymmetricKeyToString(symmKey); 

用SecretKeySpec加密數據:

private static String encryptDataWithSymmetricKey (SecretKeySpec symmKey, String data) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { // encryption byte[] toBeCiphred = data.getBytes("UTF-8"); String encryptedData = null; try { Cipher c = Cipher.getInstance("AES"); c.init(Cipher.ENCRYPT_MODE, symmKey); byte[] encodedBytes = c.doFinal(toBeCiphred); System.out.println("BYTE STRING (ASYMM): " + encodedBytes); encryptedData = Base64.encodeToString(encodedBytes, Base64.DEFAULT); } catch (Exception e) { Log.e(TAG, "AES encryption error"); throw new RuntimeException(e); }


    return encryptedData;
}


 encryptedData = encryptDataWithSymmetricKey(symmKey, text);

使用攔截器:

而後將字符串祕密AES密鑰和加密的數據(用這個AES密鑰加密)使用okhttp使POST請求。字符串密鑰使用的是RSA加密。

public class EncryptionInterceptor implements Interceptor {

       private static final String TAG =   EncryptionInterceptor.class.getSimpleName();

       private static final boolean DEBUG = true;

       @Override
       public Response intercept(Chain chain) throws IOException {


       Request request = chain.request();
       RequestBody oldBody = request.body();
       Buffer buffer = new Buffer();
       oldBody.writeTo(buffer);
       String strOldBody = buffer.readUtf8();
       MediaType mediaType = MediaType.parse("text/plain; charset=utf-8");
       String strNewBody = encryptDataWithSymmetricKey(symmKey, text);

       RequestBody body = RequestBody.create(mediaType, strNewBody);
       request = request.newBuilder().header("Content-Type", body.contentType().toString()).header("Content-Length", String.valueOf(body.contentLength())).method(request.method(), body).build();
       return chain.proceed(request);
  }
}

在server端可以解密(從RSA)祕密AES密鑰,並獲得它的字符串表示。在client(Android)和server端(server)上是同樣的。

使用這個字符串AES密鑰解密數據

String encryptionMethod = "AES-128-CBC";  

  //decryptedAESKey is an Android AES SecretKeySpec converted  to string
  //in Android the string key was base64_encoded, 服務端解密 decode

  String secretHash = base64Decode(decryptedAESKey);


 // Decrypt
  String decryptedMessage = opensslDecrypt(base64Decode(encryptedData),  encryptionMethod, secretHash);

總結

完整的非對稱加密過程

假如現在 你向支付寶 轉帳(術語數據信息),爲了保證信息傳送的保密性、真實性、完整性和不能否認性,需要對傳送的信息進行數字加密和簽名,其傳送過程爲:

  • 1.首先你要確認是不是支付寶的數字證書,假設確以爲支付寶身份後。則對方真實可信。可以向對方傳送信息,
  • 2.你準備好要傳送的數字信息(明文)計算要轉的多少錢。對方支付寶帳號等。
  • 3.你 對數字信息進行哈希運算。獲得一個信息摘要(client主要職責);
  • 4.你 用本身的私鑰對信息摘要進行加密獲得 你 的數字簽名,並將其附在數字信息上。
  • 5.你 隨機產生一個加密密鑰,並用此password對要發送的信息進行加密(密文)。
  • 6.你用 支付寶的公鑰對剛纔隨機產生的加密密鑰進行加密,將加密後的 DES 密鑰連同密文一塊兒傳送給支付寶。
  • 7.支付寶收到 你 傳送來的密文和加密過的 DES 密鑰,先用本身的私鑰對加密的 DES 密鑰進行解密,獲得 你隨機產生的加密密鑰;
  • 8.支付寶 而後用隨機密鑰對收到的密文進行解密,獲得明文的數字信息,而後將隨機密鑰拋棄;
  • 9.支付寶 用你 的公鑰對 你的的數字簽名進行解密。獲得信息摘要;
  • 10.支付寶用一樣的哈希算法對收到的明文再進行一次哈希運算,獲得一個新的信息摘要。
  • 11.支付寶將收到的信息摘要和新產生的信息摘要進行比較。假設一致,說明收到的信息沒有被改動過。
  • 12 肯定收到信息。而後進行向對方進行付款交易,一次非對稱密過程結束。在這後面的流程就不屬於本次非對稱加密的範疇,算支付寶我的的自我流程,也就是循環以上過程。

做者/Tamic
http://blog.csdn.net/sk719887916/article/details/65448628

閱讀推薦

Retrofit/OkHttp API接口加固技術實踐(上)

相關文章
相關標籤/搜索