4

我在 Android 设备(使用 Android 6.0 的三星 Galaxy)和使用 com.sun.net.httpserver.HttpsServer 的简单 Java 应用程序之间通过 SSL (TSL) 进行通信时遇到问题。我不得不说,在其他装有 Android 4.4 的设备上一切正常。

当 Android 6.0 尝试进行握手时,服务器端完成通信,在 android 上看到下面的堆栈跟踪

W/System.err: javax.net.ssl.SSLHandshakeException: Connection closed by peer
W/System.err:     at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) 
W/System.err:     at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:353)
W/System.err:     at com.android.okhttp.internal.http.SocketConnector.connectTls(SocketConnector.java:212)
W/System.err:     at com.android.okhttp.Connection.connect(Connection.java:1322)
W/System.err:     at com.android.okhttp.Connection.connectAndSetOwner(Connection.java:1410) 
W/System.err:     at com.android.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128)
W/System.err:     at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:466)
W/System.err:     at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:447) 
W/System.err:     at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:353)
W/System.err:     at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:468) 08-28 06:47:21.322 3676-5603/pl.com.szb.gateopener W/System.err:     at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:118) 08-28 06:47:21.322 3676-5603/pl.com.szb.gateopener W/System.err:     at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:249)
W/System.err:     at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getOutputStream(DelegatingHttpsURLConnection.java:218)
W/System.err:     at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:25)
W/System.err:     at org.ksoap2.transport.HttpsServiceConnectionSE.openOutputStream(HttpsServiceConnectionSE.java:127)
W/System.err:     at org.ksoap2.transport.HttpTransportSE.sendData(HttpTransportSE.java:292) 
W/System.err:     at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:184)
W/System.err:     at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:118) 
W/System.err:     at pl.com.szb.gateopener.client.PSBGOImplPortBinding.sendRequest(PSBGOImplPortBinding.java:99)
W/System.err:     at pl.com.szb.gateopener.client.PSBGOImplPortBinding.execute(PSBGOImplPortBinding.java:284)
W/System.err:     at pl.com.szb.gateopener.client.PSBGOImplPortBinding.getGates(PSBGOImplPortBinding.java:142)
W/System.err:     at pl.com.szb.gateopener.client.PSBGOImplPortBinding$2.Func(PSBGOImplPortBinding.java:165)
W/System.err:     at pl.com.szb.gateopener.client.PSBGOImplPortBinding$2.Func(PSBGOImplPortBinding.java:163)
W/System.err:     at pl.com.szb.gateopener.client.PSBGOImplPortBinding$7.doInBackground(PSBGOImplPortBinding.java:318)
W/System.err:     at pl.com.szb.gateopener.client.PSBGOImplPortBinding$7.doInBackground(PSBGOImplPortBinding.java:308)
W/System.err:     at android.os.AsyncTask$2.call(AsyncTask.java:295) 
W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
W/System.err:     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
W/System.err:     at java.lang.Thread.run(Thread.java:818)

用于 SSL 启动的 Android 代码

 `private void initSSL() throws Exception {
    Log.d(TAG,"initSSL");
    TrustManager tm = new CustomX509TrustManager();
    SSLContext customSSLContext = SSLContext.getInstance("TLSv1.1");
    customSSLContext.init(null , new TrustManager[] { tm } , null);
    sslSocketFactory = customSSLContext.getSocketFactory();

    HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory);

    HostnameVerifier hv = new HostnameVerifier() {
        public boolean verify(String hostname, SSLSession session) {
            Log.d(TAG, String.format("Verifying %s , sessionId: %s", hostname, Arrays.toString(session.getId())));
            return true;
        }
    };
    HttpsURLConnection.setDefaultHostnameVerifier(hv);
}


public class CustomX509TrustManager implements X509TrustManager {
    private String TAG = "CustomX509TrustManager";
    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException
    {
        Log.d(TAG, "checkClientTrusted");
    }

    @Override
    public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws CertificateException
    {
        Log.d(TAG, "checkServerTrusted");
        // Here you can verify the servers certificate. (e.g. against one which is stored on mobile device)

        InputStream inStream = null;
        try {
            inStream = getResources().openRawResource(R.raw.goserver_10y);
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            X509Certificate ca = (X509Certificate) cf.generateCertificate(inStream);
            inStream.close();

            for (X509Certificate cert : certs) {
                // Verifing by public key
                cert.verify(ca.getPublicKey());
            }
        } catch (Exception e) {
            Log.w(TAG, e.getMessage());
            throw new CertificateException(e);
        } finally {
            try {
                inStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public X509Certificate[] getAcceptedIssuers() {
        Log.d(TAG, "getAcceptedIssuers");
        return null;
    }
}`

和一个服务器代码:

`private void initServer() throws Exception{
    Config config = getContext().system().settings().config();
    host = getConfigString("pl.com.szb.GOImpl.host", config, "0.0.0.0");
    port = getConfigInt("port", config, 10000);
    useSSL = getConfigBoolean("use_ssl", config, true);
    endpointLocation = getConfigString("endpointLocation", config, "/go");

    String fullURL = String.format("%s://%s:%d%s",(useSSL ? "https" : "http"), host, port, endpointLocation);
    log.info(String.format("WSDL : %s?wsdl", fullURL));

    if (useSSL) {
        keystorePass = getConfigString("keystorePass", config, "secret");
        keystoreName = getConfigString("keystoreName", config, "second/server.bks");

        char[] pass = keystorePass.toCharArray();
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream is = classLoader.getResourceAsStream(keystoreName);

        KeyStore ks = KeyStore.getInstance("BKS");
        ks.load(is, pass);

        KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX");
        kmf.init(ks, pass);

        SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
        sslContext.init(kmf.getKeyManagers(), null, null);
        server = HttpsServer.create(new InetSocketAddress(host, port), 0);

        ((HttpsServer)server).setHttpsConfigurator(new HttpsConfigurator(sslContext) {
            public void configure(HttpsParameters params) {
                try {
                    log.debug(String.format("Got client: %s, wantAuth: %b, needAuth: %b",
                        params.getClientAddress().toString(),
                        params.getWantClientAuth(),
                        params.getNeedClientAuth()
                    ));

                    params.setWantClientAuth(false);
                    params.setNeedClientAuth(false);

                    //what to do more??

                } catch (Exception ex) {
                    log.warn(String.format("Failed to create HTTPS port, cause " + ex.getMessage()));
                }
            }
        });
    } else {
        server = HttpServer.create(new InetSocketAddress(host, port), 0);
    }
   server.setExecutor(java.util.concurrent.Executors.newCachedThreadPool());
    server.start();

    HttpContext httpContext = server.createContext(endpointLocation);
    endpoint = Endpoint.create(SOAPBinding.SOAP11HTTP_BINDING,this);
    endpoint.publish(httpContext);
}

`

我检查过的内容:

  • 输入标题后 google 和 stackoverflow 建议的每个链接(特别是链接Https 连接在 android 5.0 lollipop 中被对等方关闭- 但没有运气)
  • 两个设备上的 Cipher siute 理论上都应该能够完成握手。有相应的算法。
  • 我检查了与wireshark的通信。我发现即使我 delcare(在 Android 中)TLSv1.2 版本 TLS 1.0 在 SSL 标头中发送(请参阅 附加的 wireshark 转储- 使用“解码为”-> SSL)在第 140 行我们看到来自 Android 6.0 的通信,Bellow(在第 145 行,我们看到来自 Android 4.4 的工作通信)10.0.0.203 是 Android 6.0,10.0.0.99 是服务器,10.0.0.200 是 Android 4.4
  • 我读到“连接被对等方关闭”并且在许多主题中人们都在谈论错误的证书,但就我而言,我认为 SSL 在协议协商期间崩溃,而不是在证书交换期间(稍后出现)。

服务器站点有点旧(它是一个 SOAP 服务),但我认为服务器提供什么并不重要。

请帮忙,这是我的第一篇文章。

4

0 回答 0