【问题标题】:SSLHandshakeException - handshake failed on Android 6.0SSLHandshakeException - Android 6.0 上的握手失败
【发布时间】:2016-10-02 05:21:29
【问题描述】:

我正在开发一个需要通过 HTTPS 连接下载的 android 应用程序。但我得到了 SSLHandshakeException - 握手失败。

我所做的如下

首先,使用openssl获取服务器证书链

openssl s_client -connect www.coles.com.au:443

得到了

Certificate chain
 0 s:/C=AU/ST=Victoria/L=Hawthorn East/O=Coles Supermarkets Australia Pty Ltd/OU=Web Team/CN=coles.com.au
   i:/C=US/O=thawte, Inc./CN=thawte SSL CA - G2
 1 s:/C=US/O=thawte, Inc./CN=thawte SSL CA - G2
   i:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIE3zCCA8egAwIBAgIQfc9y5DSMNxERU663wd4m+DANBgkqhkiG9w0BAQsFADBB
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3RlLCBJbmMuMRswGQYDVQQDExJ0
aGF3dGUgU1NMIENBIC0gRzIwHhcNMTUxMDMwMDAwMDAwWhcNMTgxMDI5MjM1OTU5
WjCBkTELMAkGA1UEBhMCQVUxETAPBgNVBAgMCFZpY3RvcmlhMRYwFAYDVQQHDA1I
YXd0aG9ybiBFYXN0MS0wKwYDVQQKDCRDb2xlcyBTdXBlcm1hcmtldHMgQXVzdHJh
bGlhIFB0eSBMdGQxETAPBgNVBAsMCFdlYiBUZWFtMRUwEwYDVQQDDAxjb2xlcy5j
b20uYXUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBoLhSH1Q/3YGQ
d0d5FEza3EaW4bWYDfHtg0oReJ8OvONWYpPgKZ0HZPUi6m6CDhWKXRmxZbiRDGQR
ihRYpAcRnw/DbkN6+eDSHU0I5eZD4YpdbhvAzeVOkiSyQXipvAJZFvomHsjCIvIu
g/2EInwAeTkgDSJY+PUbiiy+Ooko/H2XpjV0+C3eb2RY/pNV+Df5FG1bzVtEWNna
ncqYK9tJlyfDNM9TENzZdxmLtJsFYzlniJcxVgjPw4uSI4N3Cnr3n3PuSKSQuavl
D7k4H7wuwPvOn6l1wAj7fbgq16ZfF9vUvLXsn/yc99V1/7oYIVA4KDxgLhU10IVp
k2JPDZN9AgMBAAGjggGAMIIBfDApBgNVHREEIjAgghB3d3cuY29sZXMuY29tLmF1
ggxjb2xlcy5jb20uYXUwCQYDVR0TBAIwADBuBgNVHSAEZzBlMGMGBmeBDAECAjBZ
MCYGCCsGAQUFBwIBFhpodHRwczovL3d3dy50aGF3dGUuY29tL2NwczAvBggrBgEF
BQcCAjAjDCFodHRwczovL3d3dy50aGF3dGUuY29tL3JlcG9zaXRvcnkwDgYDVR0P
AQH/BAQDAgWgMB8GA1UdIwQYMBaAFMJPSFf80U+awF04fQ4F29kutVJgMCsGA1Ud
HwQkMCIwIKAeoByGGmh0dHA6Ly90ai5zeW1jYi5jb20vdGouY3JsMB0GA1UdJQQW
MBQGCCsGAQUFBwMBBggrBgEFBQcDAjBXBggrBgEFBQcBAQRLMEkwHwYIKwYBBQUH
MAGGE2h0dHA6Ly90ai5zeW1jZC5jb20wJgYIKwYBBQUHMAKGGmh0dHA6Ly90ai5z
eW1jYi5jb20vdGouY3J0MA0GCSqGSIb3DQEBCwUAA4IBAQAkm5BJW0u7ZJFGVWip
xo/poAFHNMImBfofz8WJGN/npJwLKV0mV8FX6dRPEAjPWWT+I/JonwX7VVxAgUWj
3bl+XdIU3hj8cRh3yDnEvhKVKs3orr/jQnxSNx4JZCwmPUIuKK58R1dYCRV/hT7l
YYDMXj+RrAjhrgu7IgZJDCV9kcznBqMdbHLOb/P4PX6j8CsCufS6iGjKhBHTL/49
uuL9ACqH6BgGVctm4kELGcyS6e+VJ9rHI3P+1muOk4wKEVjps9rbPOmpUTk8WhXb
RghAwHrtQZEZMIAVMg2ksCkl/NGRl64Q1W/lW2JHun6ApdXPsGzTvzp3+Kmhrf5p
mLNK
-----END CERTIFICATE-----
subject=/C=AU/ST=Victoria/L=Hawthorn East/O=Coles Supermarkets Australia Pty Ltd/OU=Web Team/CN=coles.com.au
issuer=/C=US/O=thawte, Inc./CN=thawte SSL CA - G2
---
No client certificate CA names sent
Peer signing digest: SHA1

然后去 thawte 网站(https://search.thawte.com/support/ssl-digital-certificates/index?page=content&id=SO26817&actp=RSS&viewlocale=en_US#links) 下载 CA 证书(告诉我是我做错了还是从错误的地方下载)是 thawte_SSL_CA_G2.cer

第三,我有下面的代码来连接

String url = "https://www.coles.com.au";
        String strContent = "";
        HttpURLConnection connection;

        AssetManager assetManager = context.getAssets();
        InputStream caInput = null;

        try{
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            caInput = assetManager.open("thawte_SSL_CA_G2.cer");
            Certificate ca = cf.generateCertificate(caInput);

            String keyStoreType = KeyStore.getDefaultType();
            KeyStore keyStore = KeyStore.getInstance(keyStoreType);
            keyStore.load(null, null);
            keyStore.setCertificateEntry("ca", ca);

            String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
            tmf.init(keyStore);

            SSLContext context = SSLContext.getInstance("TLS");
            context.init(null, tmf.getTrustManagers(), null);

            URL urlObj = new URL(url);

            HttpsURLConnection urlConnection =
                    (HttpsURLConnection)urlObj.openConnection();
            urlConnection.setSSLSocketFactory(context.getSocketFactory());
            InputStream in = urlConnection.getInputStream();

            BufferedReader reader = new BufferedReader(new InputStreamReader(in));

            while(null != (strContent= reader.readLine())){
                System.out.println(strContent);
            }
        }
        catch (IOException e){
             String exception = e.getMessage();
            System.out.println(exception);
        }

我用wireshark捕捉并观察下面发生的事情

-> Client Hello
<- Server Hello
<- Certificate
<- Server Key Exchange
-> Client Key Exchange, Change Cipher Spec, Hello Request, Hello Request
<- FIN

请帮助我了解握手失败的原因。

【问题讨论】:

  • 相关,请使用以下openssl s_client -connect www.coles.com.au:443 -tls1 -servername www.coles.com.au。这将为您提供 TLS 1.0(不是 SSLv3),并使用服务器名称指示 (SNI)。
  • @jww 通过使用您的命令,检索到相同的结果。我得到了正确的证书吗?

标签: java android ssl openssl tls1.2


【解决方案1】:

您应该添加所有 ICA(中间证书)和 CA。

你可以这样做

openssl s_client -showcerts -connect  www.coles.com.au:443 

将您收到的所有证书添加到您的信任库。 (严格来说只有 ICA 和 CA 在信任库中就足够了)

【讨论】:

  • 服务器配置错误。它应该发送所有必要的中间体。另请参阅 OWSP TLS 备忘单上的 Rule - Always Provide All Needed Certificates。客户端仍需要信任根 CA。它也可以信任中间 CA。在这种情况下,无需信任根 CA。最后,网站管理员需要修复他们的服务器。
  • 是的,您的正确服务器应该提供所有证书链,并且在您的 java 应用程序中,您应该将所有 ICA 与 CA 添加到信任存储区以验证最终实体证书。
  • @RaghuKNair 我通过将别名都指定为“CA”将所有 ICA 和 CA 添加到密钥库中,然后我看到 SSLHandshakeException - 找不到证书路径的信任锚。我可以在 jww 解决的文档中看到它,但是我应该怎么做才能修复它?
猜你喜欢
  • 2017-10-17
  • 1970-01-01
  • 1970-01-01
  • 2015-01-13
  • 2020-04-25
  • 2016-01-18
  • 2017-12-14
  • 2016-01-05
  • 2017-06-21
相关资源
最近更新 更多