简体   繁体   English

以编程方式记录 SSL 证书

[英]Log the SSL Certificate programmatically

I have 2 devices in the wild that are not able to connect to my TLS v1.2 endpoint.我有 2 个无法连接到我的 TLS v1.2 端点的设备。 All others seem able to, including browsers, PostMan and iOS devices.所有其他设备似乎都可以,包括浏览器、邮递员和 iOS 设备。

The devices are running Android 5 & 7 (so there should not be a problem with the TLS v1.2 support).这些设备运行的是 Android 5 和 7(因此 TLS v1.2 支持应该没有问题)。

Note: This is not a self-signed certificate.注意:这不是自签名证书。 It is signed by Amazon.它由亚马逊签署。

Immediate thoughts were:直接的想法是:

  1. Android fragmentation - perhaps the devices (one is a Kindle Fire 7) are not including the correct certificates into the OS. Android 碎片化 - 也许设备(一个是 Kindle Fire 7)没有在操作系统中包含正确的证书。 It wouldn't be the first time that a device manufacturer made an odd decision that breaks functionality.这不是设备制造商第一次做出破坏功能的奇怪决定。

  2. API is being accessed via a proxy, and there actually is a Man-In-The-Middle, correctly being detected. API 是通过代理访问的,实际上一个中间人,被正确检测到。


Fixing (1) means bundling our certificate, and leads to the usual problems when our cert expires.修复(1)意味着捆绑我们的证书,并在我们的证书过期时导致通常的问题。

I would prefer to get the user to install a debug build that confirms whether (1) or (2) is the problem.我更愿意让用户安装一个调试版本,以确认 (1) 还是 (2) 是问题所在。 Such build would inspect the SSL Certificate provided by the server/proxy, and log that back to me.这样的构建将检查服务器/代理提供的 SSL 证书,并将其记录回给我。


Web Frameworks:网络框架:

  • Retrofit v2.3.0改造 v2.3.0
  • OkHttp v3.9.1 OkHttp v3.9.1

Question:题:

How do I inspect the information of the SSL Certificate that the device is seeing when hitting my endpoint?如何检查设备在访问我的端点时看到的 SSL 证书的信息?


Update per comment from @SangeetSuresh :更新@SangeetSuresh 的每条评论

It turns out there are 2 different exceptions being thrown.事实证明,抛出了 2 个不同的异常。

The Kindle Fire 7" Tablet (KFAUWI, OS 5.1.1) is throwing the one I have started to investigate, which this question is meant to have focused on. ie basic SSL failure. 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)

The LG device (LG-SP200, OS 7.1.2) is having the connection closed by the peer, which should be addressed under a new question if not solved here: 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)

Robby Cornelissen provided the basic answer in a comment referencing the OkHttp Response : Robby Cornelissen 引用 OkHttp Response 的评论中提供了基本答案

the information should be available from response.handshake().peerCertificates() .该信息应该可以从response.handshake().peerCertificates()

A simple Interceptor was implemented to inspect the certificates, given a valid handshake:在有效握手的情况下,实现了一个简单的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;
    }
}

This gets added to the OkHttpClient as per normal:这将按照正常方式添加到OkHttpClient中:

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

A similar solution was proposed by Sangeet Suresh that references the Retrofit Response object: Sangeet Suresh提出了一个类似的解决方案,它引用了 Retrofit Response对象:

response?.raw()?.handshake() I think this will help you response?.raw()?.handshake()我认为这会帮助你

Here the important information being the fact that Retrofit gives access to the raw OkHttp response in this manner.这里的重要信息是 Retrofit 以这种方式提供对原始 OkHttp 响应的访问。

This would not be used in an Interceptor but rather at a higher level, in the actual Retrofit handling code, after getting a Retrofit Response<> from the API.这不会在Interceptor使用,而是在更高级别使用,在实际的 Retrofit 处理代码中,在从 API 获取 Retrofit Response<>

Converting his Kotlin solution back to Java could yield something like this:将他的 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());
            }
        }
    }
}

Both solutions work fine, provided the handshake() is not null ie when the handshake succeeds.两种解决方案都可以正常工作,前提是handshake()不为空,即握手成功时。

Given that this is an investigation into failed handshakes, a further step was required to "trust all certificates" (NB debug builds only!).鉴于这是对失败握手的调查,需要进一步“信任所有证书”(仅限 NB 调试版本!)。

This has been documented many times - here is one such version:这已被多次记录 - 这是一个这样的版本:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM