2017-02-10 63 views
2

我想要做的事情非常簡單 - 我想從iOS和Android應用連接到服務器時獲得完整的證書鏈。無法從Android鏈中獲取根CA證書

在iOS中,我使用NSURLSession和壓倒一切的URLSession:didReceiveChallenge:方法,其中,我能夠獲得在這種情況下看起來像預期的證書鏈:

[leaf certificate] - [intermediate certificate] - [root certificate]

可愛。

現在我正嘗試在Android設備上使用HttpsURLConnection做同樣的事情。連接到服務器後,我正在使用getServerCertificates()方法獲得證書鏈(或至少我希望這是它的方法)。這將返回我Certificate[]對象,其中我得到看起來像這樣的鏈條:

[leaf certificate] - [intermediate certificate]

因此,Android設備上沒有根證書。

你有什麼想法如何從Android鏈中獲取根證書?

預先感謝您。

回答

2

你的問題只是顯而易見的。我正在審閱TLS規範中的服務器證書部分。看到這個post

服務器必須發送一個命令者證書鏈開始,服務器證書和中間體但CA根是可選的,因爲是由標準的根證書被獨立分佈的需要。服務器通常不包含CA root

客戶端驗證在尋找信任庫中的根CA的鏈。驗證由X509TrustManager進行,希望返回發現的根證書,但是,正如你所看到的,負責驗證完成的方法默默

public void checkServerTrusted(X509Certificate[] chain, String authType) 

編輯 - 如何從一個HTTPS受信任的根連接

您可以使用可用可信證書列表來驗證中間證書,以檢查其中哪些是髮卡機構。 (從herehere

TrustManagerFactory tmf = TrustManagerFactory.getInstance(
     TrustManagerFactory.getDefaultAlgorithm()); 
// Initialise the TMF as you normally would, for example: 
tmf.init((KeyStore)null); 

//get default X509TrustManager 
TrustManager[] trustManagers = tmf.getTrustManagers(); 
final X509TrustManager x509Tm = (X509TrustManager)trustManagers[0]; 

//trusted certificate issuers 
X509Certificate issuers[] = x509Tm.getAcceptedIssuers(); 

//Perform connection... 
HttpsURLConnection conn =.... 

//get the last intermediate certificate from server certificates. 
//Fixme: if the server returns alsothe root certificate... 
Certificate cert[] = conn.getServerCertificates(); 
X509Certificate intermediate = (X509Certificate)cert[cert.length-1]; 

for (int i = 0; i < issuers.length;i++){ 
    try{ 
     intermediate.verify(issuers[i].getPublicKey()); 
      //Verification ok. issuers[i] is the issuer 
      return issuers[i]; 
     } catch (Exception e){} 
    } 
} 
+0

感謝您的回答提取的代碼。你有,爲什麼我會收到在iOS的情況下,根證書的任何解釋,但在Android上不呢?我在這兩個請求發送到相同的端點案例 – uerceg

+0

假設服務器沒有提供鏈中的根CA(您可以在ssllabs.com中查看它),iOS正在使用信任存儲的匹配證書構建完整的認證鏈,而Android正在驗證相同但仍是沒有添加根證書在我看來,Android(和Java)應該提供這些信息 – pedrofb

+0

是的,感謝你的信息,是有道理的,我試圖覆蓋'X509TrustManager',但仍然沒有運氣。你也許知道是否有安德爾的一種方式oid從設備獲取根證書,用於驗證鏈中的中間設備?(幾乎可以獲得iOS所返回的根目錄,但可能從設備本身讀取它) – uerceg