2017-02-10 157 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