Android自签名证书:未找到证书路径的信任锚点

7
我知道这个主题在很多地方都有讨论,但是在我浏览了几乎所有的内容后,我决定创建我的第一个StackOverflow问题...
问题如下:
我想连接到一个安全的webservice(https),该webservice使用证书限制访问,并使用用户名/密码对用户进行身份验证。因此,我有一个客户端证书(p12文件)和一个服务器证书(pem或der文件)。我尝试使用HttpURLConnection类,因为据我所听,Apache库将不再支持Android。
因此,这是我的实现(serverCert和clientCert是我的文件的完整路径):
        // Load CAs from our reference to the file
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream caInput = new BufferedInputStream(new FileInputStream(serverCert));
        X509Certificate serverCertificate;

        try {
            serverCertificate = (X509Certificate)cf.generateCertificate(caInput);
            System.out.println("ca=" + serverCertificate.getSubjectDN());
        } finally {
            caInput.close();
        }
        Log.d(TAG, "Server Cert: " + serverCertificate);

        // Create a KeyStore containing our trusted CAs
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        trustStore.load(null);
        trustStore.setCertificateEntry("my ca", serverCertificate);

        //Load the Client certificate in the keystore
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        FileInputStream fis = new FileInputStream(clientCert);
        keyStore.load(fis,CLIENT_PASSWORD);

        // Create a TrustManager that trusts the CAs in our KeyStore
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustStore);

        //Build the SSL Context
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(keyStore, pref.getString(Constants.clientCertificatePassword, "").toCharArray

());


    //Create the SSL context
                SSLContext sslContext = SSLContext.getInstance("TLS");
                sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
...
    //And later, we use that sslContext to initiatize the socketFactory

                urlConnection = (HttpsURLConnection) requestedUrl.openConnection();
         urlConnection.setSSLSocketFactory(CertificateManager.getInstance().getSslContext().getSocketFactory());
...

我可以创建SSLContext并显示我的两个证书内容。但是当我尝试执行HTTPS连接时,我会得到以下异常:javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException:找不到认证路径的信任锚点。你们中有人遇到过这个错误吗?你的解决方案是什么?我查看了以下这些网站(没有成功):

http://blog.chariotsolutions.com/2013/01/https-with-client-certificates-on.html

http://nelenkov.blogspot.ch/2011/12/using-custom-certificate-trust-store-on.html


我也尝试了这个解决方案(http://nelenkov.blogspot.ch/2011/12/using-custom-certificate-trust-store-on.html),但仍然收到相同的消息... 服务器配置不正确可能吗? - TheOnlyYam
2
嘿,好久不见了,你找到解决办法了吗?我也遇到了同样的问题。我有一个.pem和一个.p12文件。 - Wicked161089
1个回答

1
在您的代码中,您正在创建和初始化一个 SSLContext,但没有使用它。也许您应该替换为:

urlConnection.setSSLSocketFactory(CertificateManager.getInstance().getSslContext().getSocketFactory());

by

urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());

我建议您在可能的情况下向JVM传递选项-Djavax.net.debug=all。它将在标准输出上打印有关SSL连接和握手的详细信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接