以编程方式记录SSL证书

时间:2018-09-10 08:57:53

标签: android ssl-certificate

我有2台设备无法连接到TLS v1.2端点。似乎所有其他功能,包括浏览器,PostMan和iOS设备。

设备正在运行Android 5和7(因此TLS v1.2支持应该应该没问题)。

注意:这不是自签名证书。它是由亚马逊签名的。

立即的想法是:

  1. Android碎片-可能是设备(其中一个是Kindle Fire 7) 没有在操作系统中包含正确的证书。不会的 是设备制造商第一次做出奇怪的决定 会破坏功能。

  2. 通过代理访问
  3. API,实际上是 中间人,可以被正确检测到。


修复(1)意味着捆绑我们的证书,并在我们的证书过期时导致常见问题。

我希望让用户安装一个调试版本,以确认是否是(1)或(2)。这样的构建将检查服务器/代理提供的SSL证书,并将其重新记录回我。


Web框架:

  • 改良版v2.3.0
  • OkHttp v3.9.1

问题:

在到达端点时,如何检查设备看到的SSL证书信息?


comment from @SangeetSuresh更新:

事实证明,有两种不同的异常被抛出。

Kindle Fire 7英寸平板电脑(KFAUWI,OS 5.1.1)正在抛出我已经开始研究的平板电脑,这个问题本来是要针对的,即基本的SSL失败。

java.security.cert.CertPathValidatorException: 
    Trust anchor for certification path not found.
       at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:331)
       at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:232)
       at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:114)

LG设备(LG-SP200,OS 7.1.2)的连接已被对等方关闭,如果此处未解决,应在一个新问题下解决该问题:

javax.net.ssl.SSLHandshakeException: 
    Connection closed by peer
       at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(NativeCrypto.java)
       at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:360)
       at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:299)

1 个答案:

答案 0 :(得分:1)

Robby Cornelissen提供了the basic answer in a comment,引用了OkHttp Response

  

该信息应可从   response.handshake().peerCertificates()

实施了简单的Interceptor来检查证书,并进行有效的握手:

private static class SslCertificateLogger implements Interceptor {

    public static final String TAG = "SSL";

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Response response;
        try {
            response = chain.proceed(request);
        } catch (Exception e) {
            Log.d(TAG, "<-- HTTP FAILED: " + e);
            throw e;
        }

        Handshake handshake = response.handshake();
        if (handshake == null) {
            Log.d(TAG, "no handshake");
            return response;
        }


        Log.d(TAG, "handshake success");
        List<Certificate> certificates = handshake.peerCertificates();
        if (certificates == null) {
            Log.d(TAG, "no peer certificates");
            return response;
        }

        String s;
        for (Certificate certificate : certificates) {
            s = certificate.toString();
            Log.d(TAG, s);
        }

        return response;
    }
}

这会按照常规方式添加到OkHttpClient中:

OkHttpClient.Builder builder = new OkHttpClient.Builder()
        .addInterceptor(new SslCertificateLogger())
        .build();

A similar solutionSangeet Suresh提出,它引用了改造Response对象:

  

response?.raw()?.handshake()我认为这会为您提供帮助

重要的信息是Retrofit可以通过这种方式访问​​原始的OkHttp响应。

从API获得翻版Interceptor之后,该代码将不会在Response<>中使用,而是在更高级别的实际翻版处理代码中使用。

将他的Kotlin解决方案转换回Java可能会产生如下结果:

okhttp3.Response raw = httpResponse.raw();
if (raw != null) {
    Handshake handshake = raw.handshake();
    if (handshake != null) {
        List<Certificate> certificates = handshake.peerCertificates();
        if (certificates != null) {
            for (Certificate certificate : certificates) {
                Log.d(TAG, certificate.toString());
            }
        }
    }
}

只要handshake()不为null,即握手成功时,两个解决方案都可以正常工作。

鉴于这是对握手失败的调查,因此需要进一步采取步骤以“信任所有证书”(仅NB调试版本!)。

该文档已被多次记录-这是一个这样的版本:

相关问题