java - SSLHandshakeException - Android 6.0 上的握手失败

标签 java android ssl openssl tls1.2

我正在开发一个需要通过 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

请帮我看看我握手失败的原因。

最佳答案

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

您可以执行以下操作

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

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

关于java - SSLHandshakeException - Android 6.0 上的握手失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37592408/

相关文章:

amazon-web-services - AWS Lambda 上的证书固定

PHP WebDAV 服务器证书失败

java - 使用 @Resource 注解注入(inject)的 DataSource 的生命周期/长度

java - 组合框中的项目消失

Android Realm删除对象列表的误区

Android HTTP 请求异步任务

java - 在子类中分配全局变量并在 onCreate 方法中使用它 - Android

java - Spring RestTemplate Post 收到 500 内部服务器错误

java - 简单计算器 - 文本字段问题

仅当 IIS 设置为需要 SSL 时,Java Applet 才需要身份验证