无法从Android链中获取根CA证书

时间:2017-02-10 14:32:21

标签: android ios ssl ssl-certificate x509certificate

我想做的事情很简单 - 我想从iOS和Android应用程序连接到服务器时获得完整的证书链。

在iOS中,我使用NSURLSession并覆盖URLSession:didReceiveChallenge:方法,在这种方法中我能够获得证书链,在这种情况下看起来像预期的那样:

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

可爱。

现在我尝试使用HttpsURLConnection在Android设备上做同样的事情。连接到服务器后,我使用getServerCertificates()方法获取证书链(或者至少我希望这是它的方法)。这将返回我Certificate[]对象,其中我得到的链接看起来像这样:

[leaf certificate] - [intermediate certificate]

因此,Android设备上没有根证书。

您是否知道如何从Android链中获取根证书?

提前谢谢。

1 个答案:

答案 0 :(得分:2)

你的问题显然很简单。我正在审查TLS规范中的服务器证书部分。见post

服务器必须发送orderer认证链,从服务器证书和中间商开始,但CA根是可选的,因为根证书是独立分发的标准所要求的。服务器通常不包含CA root

客户端验证链在信任库中查找根CA.验证由X509TrustManager执行。最好返回找到的根证书,但正如您所见,负责验证的方法将以静默方式完成

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

已编辑 - 如何从HTTPS连接获取受信任的root

您可以使用可用的受信任证书列表验证中间证书,以检查哪些证书是颁发者。 (摘自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){}
    }
}