使用超过 3g 时未找到证书路径的信任锚,但在 WiFi 上工作正常

Posted

技术标签:

【中文标题】使用超过 3g 时未找到证书路径的信任锚,但在 WiFi 上工作正常【英文标题】:Trust anchor for certificate path not found when using over 3g but works fine over WiFi 【发布时间】:2012-08-02 03:05:21 【问题描述】:

我的 android 项目正在使用 api 15。我正在使用 HttpsURLConnection 类通过 https 连接到服务器。在 WiFi 上一切正常,但如果我关闭 WiFi 并运行超过 3g,我会得到以下信息:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.       at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:413)
   at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:257)       at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:210)
   at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:477)
   at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:432)
   at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:282)
   at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:232)       at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:80)
   at libcore.net.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:188)       at libcore.net.http.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:280)

如果我做错了什么,为什么它可以通过 WiFi 工作?

这里有更多信息。

如果我使用openssl查看服务器证书信息,

echo | openssl s_client -connect myserver.com:443

返回服务器级别的自签名证书,而

echo | openssl s_client -connect myserver.com:443 -servername myserver.com

返回“正确”的证书。我的服务器上有多个虚拟主机,每个虚拟主机都有自己的 rapidssl 颁发的证书,所以我“认为”这意味着我需要使用启用 TLS 的客户端。至少这是我对我在 Apache 启动日志中看到的消息的解释:

Name-based SSL virtual hosts only work for clients with TLS server name indication support

如果到目前为止我是正确的,这是否意味着我的移动 3g 网络可能与 TLS 发生了冲突,或者我应该做些什么?

可以通过继承 DefaultHttpClient 并导入包含服务器自签名证书的密钥库来让事情在 3g 上运行,但这绝对不是我的首选。

【问题讨论】:

服务器的 URL 是什么? 【参考方案1】:

添加-servername 选项只是在Client Hello 消息中设置Server Name Indication 字段,这有助于我们在目标主机包含许多证书时选择正确的证书,就像您的情况一样。但是,这与问题无关。

在 SSL 握手期间,证书以主题/颁发者对的形式交付,形成证书链。

google.com 证书链如下所示:

openssl s_client -connect google.com:443
CONNECTED(00000003)
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.google.com
   i:/C=US/O=Google Inc/CN=Google Internet Authority G2
 1 s:/C=US/O=Google Inc/CN=Google Internet Authority G2
   i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
 2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
   i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
---

一旦收到,客户端会尝试从底部到顶部(根)验证链中的所有发行者。如果客户端无法验证根证书,则会出现Trust anchor for certification path not found 消息。

所以,回到 WiFi/3G 问题,您的移动网络的 DNS 可能无法解析证书链中的中间颁发者之一的地址。

更新:

您可以将颁发者的证书放入您的 APK 并通过 TrustManager 在您的代码中添加。这种方法可以克服接入网络的限制(如果有的话)。

【讨论】:

DNS 与证书验证到底有什么关系? 如果设备CA keystore中缺少一个中间证书,它可以通过哪个协议找到权限?此外,请检查此答案:***.com/questions/19220687/…

以上是关于使用超过 3g 时未找到证书路径的信任锚,但在 WiFi 上工作正常的主要内容,如果未能解决你的问题,请参考以下文章

“CertPathValidatorException:找不到证书路径的信任锚。”使用(a)Smack 4.0.0

Xamarin Android 问题通过 HTTPS 连接到具有自签名证书的站点:“未找到证书路径的信任锚。”

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

CertPathValidatorException:找不到证书路径的信任锚 - Retrofit Android

CertPathValidatorException:找不到证书路径的信任锚

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