【问题标题】:Could not validate certificate signature?无法验证证书签名?
【发布时间】:2011-11-27 03:13:46
【问题描述】:

我从这边使用 SSL Socket 和 Trustmanager Self signed SSL

但我不断收到以下错误:

09-28 19:52:41.942: WARN/System.err(10101): javax.net.ssl.SSLHandshakeException: org.bouncycastle.jce.exception.ExtCertPathValidatorException: 无法验证证书签名。

怎么了? 我已经检查了 stackoverflow 上的不同帖子,但我似乎无法让它工作。

我的代码:

SchemeRegistry schemeRegistry = new SchemeRegistry();

// http scheme

schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));

// https scheme

schemeRegistry.register(new Scheme("https", new EasySSLSocketFactory(), 443));
params = new BasicHttpParams();
params.setParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 1);
params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean(1));
params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, false);
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, "utf8");
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(new AuthScope("www.example.com", AuthScope.ANY_PORT),
    new UsernamePasswordCredentials("user", "password"));
clientConnectionManager = new ThreadSafeClientConnManager(params, schemeRegistry);
context = new BasicHttpContext();
context.setAttribute("http.auth.credentials-provider", credentialsProvider);

DefaultHttpClient client = new DefaultHttpClient(clientConnectionManager, params);

HttpGet get = new HttpGet("https://www.example.com/web/restricted/form/formelement=512663");
HttpResponse response = client.execute(get, context);

Log.w("Response ","Status line : "+ response.toString());

【问题讨论】:

  • 您可能还想检查手机上的日期和时间设置。如果时钟太不同步,您可能会遇到与此类似的错误。
  • 如果您使用 Fuel 作为 REST 库,请参阅 stackoverflow.com/questions/47460211/…

标签: android https x509certificate


【解决方案1】:

更新

我在 API 16 模拟器上也遇到了另一个错误:

routines:SSL23_GET_SERVER_HELLO:tlsv1 警报协议版本 (外部/openssl/ssl/s23_clnt.c:741'.

阅读12,我更改了代码:

val okHttpClient = getOkHttpBuilder().build()

private fun getOkHttpBuilder(): OkHttpClient.Builder {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        Security.insertProviderAt(Conscrypt.newProvider(), 1)
    }
    return OkHttpClient().newBuilder()
}

// build.gradle:
implementation 'org.conscrypt:conscrypt-android:2.5.1'

但是library 增加了 3.4 Mb 到 apk。

我还从MyApplication 中删除了这些行:

try {
    ProviderInstaller.installIfNeeded(applicationContext)
    val sslContext = SSLContext.getInstance("TLSv1.2")
    sslContext.init(null, null, null)
    sslContext.createSSLEngine()
} catch (e: GooglePlayServicesRepairableException) {
    Timber.e(e.stackTraceToString())
    // Prompt the user to install/update/enable Google Play services.
    GoogleApiAvailability.getInstance().showErrorNotification(this, e.connectionStatusCode)
} catch (e: GooglePlayServicesNotAvailableException) {
    Timber.e(e.stackTraceToString())
    // Prompt the user to install/update/enable Google Play services.
    // GoogleApiAvailability.getInstance().showErrorNotification(this, e.errorCode)
} catch (e: NoSuchAlgorithmException) {
    Timber.e(e.stackTraceToString())
} catch (e: KeyManagementException) {
    Timber.e(e.stackTraceToString())
}

=== 旧答案 ===

在我的例子中,Android 4 和 5 出现以下错误:

原因: com.android.org.bouncycastle.jce.exception.ExtCertPathValidatorException: 无法验证证书:证书于 5 月 30 日星期六过期 2020 年 10:48:38 GMT+00:00(与 8 月 13 日星期四 11:47:00 GMT+00:00 相比) 2020)

...

引起:java.security.cert.CertificateExpiredException: 证书于 2020 年 5 月 30 日星期六 10:48:38 GMT+00:00 到期(相比 8 月 13 日星期四 11:47:00 GMT+00:00 2020)

服务器出现证书错误(可能已过期)。

对于Retrofit,请参阅https://stackoverflow.com/a/60507560/2914140。如果您使用 Fuel 作为 REST 库,请参阅 kotlin library that can do httpS connection without certificate verification (like curl --insecure)

您可以信任所有证书,但这很危险。

import java.security.SecureRandom
import java.security.cert.X509Certificate
import javax.net.ssl.*
import javax.security.cert.CertificateException

companion object {

    private val gson: Gson
    private val retrofit: Retrofit

    init {

        val okHttpClient = getOkHttpBuilder().build()

        gson = GsonBuilder().setLenient().create()

        retrofit = Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build()
    }

    private fun getOkHttpBuilder(): OkHttpClient.Builder =
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            OkHttpClient().newBuilder()
        } else {
            getUnsafeOkHttpClient()
        }

    private fun getUnsafeOkHttpClient(): OkHttpClient.Builder =
        try {
            // Create a trust manager that does not validate certificate chains
            val trustAllCerts: Array<TrustManager> = arrayOf(
                object : X509TrustManager {
                    @Throws(CertificateException::class)
                    override fun checkClientTrusted(chain: Array<X509Certificate?>?,
                                                    authType: String?) = Unit

                    @Throws(CertificateException::class)
                    override fun checkServerTrusted(chain: Array<X509Certificate?>?,
                                                    authType: String?) = Unit

                    override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
                }
            )
            // Install the all-trusting trust manager
            val sslContext: SSLContext = SSLContext.getInstance("SSL")
            sslContext.init(null, trustAllCerts, SecureRandom())
            // Create an ssl socket factory with our all-trusting manager
            val sslSocketFactory: SSLSocketFactory = sslContext.socketFactory
            val builder = OkHttpClient.Builder()
            builder.sslSocketFactory(sslSocketFactory,
                trustAllCerts[0] as X509TrustManager)
            builder.hostnameVerifier { _, _ -> true }
            builder
        } catch (e: Exception) {
            throw RuntimeException(e)
        }
}

另请参阅https://stackoverflow.com/a/60507560/2914140 了解 Android 版本检查和Glide 连接。

【讨论】:

  • 我在适用于 Android 4 和 5 的 Crashlytics 上遇到了完全相同的错误,但我仍然对为什么会发生这种情况以及为什么只在这两个操作系统上发生这种情况感到非常困惑。
  • @VGM,谢谢!据我了解,在证书出现几个月的问题后,在 Android 4 和 5 中,默认情况下它无法通过新协议建立连接。因此,我们需要启用 SSL、TLS 1.2、1.3。你知道,这对我来说很难,所以我只是去掉了信任。我不知道它是否适用于所有旧设备,但适用于模拟器和一些删除信任的设备。
【解决方案2】:

检查您设备的时间,更正它,然后再次检查。

【讨论】:

    【解决方案3】:

    顺便说一句,我们可以很容易地重现这个错误——只需将手机的日期更改为几年后。

    注意:不同手机的错误可能略有不同。有些人可能会显示证书已过期。

    【讨论】:

      【解决方案4】:

      正如 Michael Levy 所提到的,我收到此异常的原因是我的 Android 模拟器打开了几天,而且时钟已经远远不同步了。一旦我重新启动模拟器,异常就消失了。

      【讨论】:

      • 我在没有 SIM 卡的物理 Galaxy Note 设备上遇到了类似的问题。有趣的是,内置浏览器运行良好。将时间同步设置更新为自动后,我不再遇到任何错误。
      • 没错,我遇到了证书握手问题,发现我的设备时间设置不正确。它被设置为过去的东西,ssl 握手失败。
      【解决方案5】:

      很可能服务器返回的证书链带有您不信任的权威。 (意味着:您的设备不知道授权证书是可信的) 解决方案:仔细检查来自 HTTPS 网站的证书,并将相应的权限添加到您的信任库 - 但这部分似乎很棘手

      (这里有一些解释: http://groups.google.com/group/android-security-discuss/browse_thread/thread/0bf726de4f5275a3/391b900631d7f358)

      【讨论】:

      • 嗨康斯坦丁,谢谢你的回复,但我想我必须以另一种方式登录这个网站,这太复杂了。我要登录的站点有一个可以通过 HTTP 提交的登录表单,然后登录通过身份验证并通过 SSL 重定向到我想要的页面。我认为带有来自 HTTPGet 的保留 cookie 的 HTTP Post 应该这样做还是?
      • 你没有做到这一点 - 你永远不会获得 HTTPS 连接。您可以通过提交 HTTP 表单来成功,但除非您对证书问题进行排序,否则通过 SSH 重定向将不起作用 - 这是您不信任服务器的一方。有趣的是,有些服务器有问题,无法验证客户端的签名(尤其是 JBoss 有这个错误)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-05-17
      • 1970-01-01
      • 2011-12-03
      • 1970-01-01
      • 1970-01-01
      • 2010-11-05
      • 1970-01-01
      相关资源
      最近更新 更多