如何信任具有交叉签名根的 SSL 证书在 android <= 5 过期

How to trust SSL certificates with cross-signed root expired on android <= 5

我在一家使用 Comodo/Sectigo SSL 证书的公司工作。但是突然之间,我们的应用程序在使用 Okhttp 客户端向服务器发送 POST 时开始抛出此错误,在 android 4 和 5 的版本中。

HTTP FAILED: javax.net.ssl.SSLHandshakeException: com.android.org.bouncycastle.jce.exception.ExtCertPathValidatorException: Could not validate certificate: Certificate expired at Sat May 30 05:48:38 CDT 2020 (compared to Mon Jun 08 23:13:02 CDT 2020)

我尝试了很多 Whosebug 解决方案,但都没有成功。然后我在 Comodo 博客上找到了这个交叉签名证书 warning

Sectigo at present offers the ability to cross-sign certificates with the AddTrust legacy root to increase support among very old systems and devices. This root is due to expire at the end of May, 2020. Any applications or installations that depend on this cross-signed root must be updated by May, 2020 or run the risk of outage or displayed error message.

我尝试了更多的方法让我的 okhttp 客户端信任证书(在 Socket 上启用了 TLS,添加了现代 TLS、TLS 版本和密码套件到 okhttp 构建器中的连接规范,将证书添加到原始资源,我也将一个自定义的 SslSocketFactory 放到客户端)但是 none 这个工作,总是抛出一个与证书有效性或握手异常相关的错误。

唯一对我有用的是制作一个不安全的 okhttp,但显然不建议在生产中使用它。

该应用程序在 android > 5 上运行良好,但我们仍然有一些用户在 android 5 甚至 4 上由于这个问题无法使用该应用程序。还有什么办法可以实现 android <= 5 信任这个过期的 root?

感谢您的帮助

如果证书在其他方面有效,这应该有望解决问题。

在您的构建文件中

  implementation 'org.conscrypt:conscrypt-android:2.5.1'

并在您请求之前激活 Conscrypt

import org.conscrypt.Conscrypt


Security.insertProviderAt(Conscrypt.newProvider(), 1)
val client = OkHttpClient.Builder().build()

val request = Request.Builder().url("https://status.datadoghq.com/").build()
client.newCall(request).execute().use { response ->
  println(response.code())
}

如果在此之后它仍然失败,那么您可能还需要注册一个自定义证书,但请先在没有这个的情况下进行测试。

https://github.com/square/okhttp/blob/okhttp_3.12.x/samples/guide/src/main/java/okhttp3/recipes/CustomTrust.java