java.security.cert.CertPathValidatorException:未找到证书路径的信任锚.Android 2.3

jos*_*eph 11 java security ssl android android-sdk-2.3

在我的服务器(生产服务器)中,我有一个goDaddy ssl证书.我有iOS和Android应用程序连接服务器,iOS连接没有问题,Android连接版本4.*一切都很好,但设备2.3.*我总是得到SSLHandshakeException.

我确实喜欢Android开发者页面(https://developer.android.com/training/articles/security-ssl.html).

我已经在stackoverflow中看到了类似的线程(这里),但没有人帮忙.

然后我看到这个线程谈论扩展密钥用法,但在调试时我得到以下信息:

[2]: OID: 2.5.29.37, Critical: false
Extended Key Usage: [ "1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.2" ]
Run Code Online (Sandbox Code Playgroud)

所以我猜证书不是"强制"扩展密钥用法.

同样在线程有一些其他可能的原因,如日期/时间是完全地错了,至极都是不存在的.

考虑到这一点,我现在不知道问题可能在哪里.

有什么建议?

编辑: StackTrace如下:

08-04 16:54:30.139: W/System.err(4832): Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
08-04 16:54:30.149: W/System.err(4832):     at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:161)
08-04 16:54:30.149: W/System.err(4832):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:664)
08-04 16:54:30.149: W/System.err(4832):     at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
08-04 16:54:30.159: W/System.err(4832):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:474)
Run Code Online (Sandbox Code Playgroud)

Jos*_*osh 5

我在SO和网络上经历了很多地方来解决这个问题.这是适合我的代码(Android 21):

ByteArrayInputStream derInputStream = new ByteArrayInputStream(app.certificateString.getBytes());
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509","BC");
X509Certificate cert = (X509Certificate) certificateFactory.generateCertificate(derInputStream);
String alias = "alias";//cert.getSubjectX500Principal().getName();

KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null);
trustStore.setCertificateEntry(alias, cert);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
kmf.init(trustStore, null);
KeyManager[] keyManagers = kmf.getKeyManagers();

TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init(trustStore);
TrustManager[] trustManagers = tmf.getTrustManagers();

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagers, trustManagers, null);
URL url = new URL(someURL);
conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(sslContext.getSocketFactory());
Run Code Online (Sandbox Code Playgroud)

app.certificateString 是包含证书的String,例如:

static public String certificateString=
    "-----BEGIN CERTIFICATE-----\n" +
    "MIIGQTCCBSmgAwIBAgIHBcg1dAivUzANBgkqhkiG9w0BAQsFADCBjDELMAkGA1UE" +
    "BhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsTIlNlY3VyZSBE" +
    ... a bunch of characters...
    "5126sfeEJMRV4Fl2E5W1gDHoOd6V==\n" +
    "-----END CERTIFICATE-----";
Run Code Online (Sandbox Code Playgroud)

我已经测试过你可以在证书字符串中放置任何字符,如果它是自签名的,只要你保持上面的确切结构.我用笔记本电脑的终端命令行获取了证书字符串.我需要了解更多细节,请告诉我.


小智 5

如果以上所有答案都不起作用,并且在使用 android 30 作为编译和目标 sdk 版本时,您在发布应用程序时遇到任何类型的问题。请从服务器下载您的 ssl .cert 文件。并将其放入 raw 文件夹中。在 XML 文件夹中创建 network_security_config。在应用程序标签内的菜单中使用行

android:networkSecurityConfig="@xml/network_security_config"

并在 network_security_config 文件中使用下面提到的代码。

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
    <domain includeSubdomains="true">your server domain</domain>
    <trust-anchors>
        <certificates src="@raw/your server cerificate file name"/>
    </trust-anchors>
</domain-config>
</network-security-config>
Run Code Online (Sandbox Code Playgroud)


use*_*372 4

您的证书的颁发者似乎不在 2.3 设备的信任存储中。

查看您的 GoDaddy 证书的根和中间 ca,并检查您的 2.3 设备上是否存在这些证书。

请参阅http://www.andreabaccega.com/blog/2010/09/23/android-root-certification-authorities-list/以获取 2.3 证书列表。

当只有根 CA 可用时,请确保您的网络服务器还根据请求提供中间证书。