2017-06-19 103 views
7

我正在閱讀有關Android上的證書鎖定,我很困惑。我沒有使用okhttp或改造,所以我必須手動完成。 這裏有一個教程:https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#Android 他們將證書添加到可信證書列表中。但是當我們檢查安裝在服務器上的證書的sha256的base64時,還有另一個教程:https://medium.com/@appmattus/android-security-ssl-pinning-1db8acb6621e 哪種方法是正確的? 爲什麼我們不能像瀏覽器那樣從頭部的服務器接收sha256並將它存儲在某個地方?與Robospice Android上的證書鎖定

回答

0

我會推薦這
https://www.paypal-engineering.com/2015/10/14/key-pinning-in-mobile-applications/

的Android方法

最簡單的方法是使用基於JSEE-方法如下所示。這是Android推薦的方法。該方法的輸入參數是一個HTTPS連接和一組針對目標URL的有效引腳。


private boolean validatePinning(HttpsURLConnection conn, Set<String> validPins) { 
    try { 
     Certificate[] certs = conn.getServerCertificates(); 
     MessageDigest md = MessageDigest.getInstance("SHA-256"); 
     for (Certificate cert : certs) { 
      X509Certificate x509Certificate = (X509Certificate) cert; 
      byte[] key = x509Certificate.getPublicKey().getEncoded(); 
      md.update(key, 0, key.length); 
      byte[] hashBytes = md.digest(); 
      StringBuffer hexHash = new StringBuffer(); 
      for (int i = 0; i < hashBytes.length; i++) { 
       int k = 0xFF & hashBytes[i]; 
       String tmp = (k<16)? "0" : ""; 
       tmp += Integer.toHexString(0xFF & hashBytes[i]); 
       hexHash.append(tmp); 
      } 
      if (validPins.contains(hexHash.toString())) { 
       return true; 
      } 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
     return false; 
    } 
    return false; 
} 

引腳被聲明爲字符串。例如:

聲明鎖簧

private static final Set<String> PINS = new HashSet<String>(Arrays.asList(
     new String[]{ 
       "996b510ce2380da9c738...87cb13c9ec409941", 
       "ba47e83b1ccf0939bb40d2...edf856ba892c06481a"})); 

利用上述方法,這裏是展示如何能夠投入使用的例子。唯一相關部分在下面突出顯示。

實施例使用密鑰鋼釘

protected String doInBackground(String... urls) { 
    try { 
     /** Test pinning given the target URL **/ 
     /** for now use pre-defined endpoint URL instead or urls[0] **/ 
     Log.i(LOG_TAG, "==> PinningTestTask launched."); 
     String dest = defaultEndpoint; 
     URL targetURL = new URL(dest); 
     HttpsURLConnection targetConnection = (HttpsURLConnection) targetURL.openConnection(); 
     targetConnection.connect(); 
     if (validatePinning(targetConnection, PINS)) { 
      final String updateText = "Key pinning succeded for: " + dest; 
      runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        textView.setText(updateText); 
       } 
      }); 
     } else { 
      final String updateText = "Key pinning failed for: " + dest; 
      runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        textView.setText(updateText); 
       } 
      }); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
     final String updateText = "Key pinning failed for: " + dest + "\n" + e.toString(); 
     runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
       textView.setText(updateText); 
      } 
     }); 
    } 
    return null; 
} 
+0

根據https://medium.com/@appmattus/android-security-ssl-pinning-1db8acb6621e這種方法就是無效: '更好的解決方案是把PayPal在移動應用程序中的關鍵固定中轉發,但是這受到了「無效證書固定實現的考試」中討論的安全缺陷的影響。建議的代碼檢查針對httpsUrlConnection.getServerCertificates()的針腳,該針腳從服務器返回證書建議列表,並且不一定信任該設備。 – falsetto