如何修复 javax.net.ssl.SSLHandshakeException:没有共同的密码套件? [复制]

Posted

技术标签:

【中文标题】如何修复 javax.net.ssl.SSLHandshakeException:没有共同的密码套件? [复制]【英文标题】:How can I fix javax.net.ssl.SSLHandshakeException: no cipher suites in common? [duplicate] 【发布时间】:2014-05-07 14:35:46 【问题描述】:

我知道那里有很多类似的主题,但是这些主题中提供的解决方案都没有帮助我,所以这里有另一个。

我有一个与 Java 服务器通信的 android 客户端。我希望通信安全,所以我使用 SSL。但是,握手失败并出现以下错误:

来自 logcat:

03-28 03:31:30.171: W/System.err(1214): javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb81201c8: Failure in SSL library, usually a protocol error
03-28 03:31:30.171: W/System.err(1214): error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:741 0xad3cdd5c:0x00000000)
03-28 03:31:30.181: W/System.err(1214):     at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:448)
03-28 03:31:30.181: W/System.err(1214):     at com.myapp.ServerCon.getSecureSocket(ServerCon.java:362)
03-28 03:31:30.181: W/System.err(1214):     at com.myapp.ServerCon.access$0(ServerCon.java:310)
03-28 03:31:30.181: W/System.err(1214):     at com.myapp.ServerCon$1.doInBackground(ServerCon.java:283)
03-28 03:31:30.181: W/System.err(1214):     at com.myapp.ServerCon$1.doInBackground(ServerCon.java:1)
03-28 03:31:30.191: W/System.err(1214):     at android.os.AsyncTask$2.call(AsyncTask.java:288)
03-28 03:31:30.191: W/System.err(1214):     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
03-28 03:31:30.191: W/System.err(1214):     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
03-28 03:31:30.191: W/System.err(1214):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
03-28 03:31:30.191: W/System.err(1214):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
03-28 03:31:30.191: W/System.err(1214):     at java.lang.Thread.run(Thread.java:841)
03-28 03:31:30.191: W/System.err(1214): Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb81201c8: Failure in SSL library, usually a protocol error
03-28 03:31:30.191: W/System.err(1214): error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:741 0xad3cdd5c:0x00000000)
03-28 03:31:30.191: W/System.err(1214):     at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
03-28 03:31:30.191: W/System.err(1214):     at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:405)
03-28 03:31:30.191: W/System.err(1214):     ... 10 more

在服务器上使用 java -Djavax.net.debug=ssl,handshake -jar myserver.jar:

adding as trusted cert:
  Subject: EMAILADDRESS=mymail@ex.com, CN=myname, L=Stockholm, C=SV
  Issuer:  EMAILADDRESS=mymail@ex.com, CN=myname, L=Stockholm, C=SV
  Algorithm: RSA; Serial number: 0xe63fe3941be0b4a5
  Valid from Tue Mar 25 11:40:58 CET 2014 until Wed Mar 25 11:40:58 CET 2015

trigger seeding of SecureRandom
done seeding SecureRandom

Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
    Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 for SSLv2Hello
    Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 for SSLv2Hello
    Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 for SSLv2Hello
    Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 for SSLv2Hello
    Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 for SSLv2Hello

Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 for SSLv2Hello
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 for SSLv2Hello
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 for SSLv3
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 for SSLv3
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 for SSLv3
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 for SSLv3
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 for SSLv3
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 for SSLv3
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 for SSLv3
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 for TLSv1.1
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 for TLSv1.1
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 for TLSv1.1
Thread-1, READ: TLSv1 Handshake, length = 179
*** ClientHello, TLSv1
RandomCookie:  GMT: 1395989998 bytes =  111, 250, 184, 147, 57, 151, 111, 1, 186, 199, 20, 220, 158, 177, 180, 53, 61, 151, 68, 38, 40, 140, 252, 173, 103, 147, 144, 88 
Session ID:  
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods:   0 
Extension ec_point_formats, formats: [uncompressed, ansiX962_compressed_prime, ansiX962_compressed_char2]
Extension elliptic_curves, curve names: sect571r1, sect571k1, secp521r1, sect409k1, sect409r1, secp384r1, sect283k1, sect283r1, secp256k1, secp256r1, sect239k1, sect233k1, sect233r1, secp224k1, secp224r1, sect193r1, sect193r2, secp192k1, secp192r1, sect163k1, sect163r1, sect163r2, secp160k1, secp160r1, secp160r2
***
%% Initialized:  [Session-1, SSL_NULL_WITH_NULL_NULL]
%% Invalidated:  [Session-1, SSL_NULL_WITH_NULL_NULL]
Thread-1, SEND TLSv1 ALERT:  fatal, description = handshake_failure
Thread-1, WRITE: TLSv1 Alert, length = 2
Thread-1, called closeSocket()
Thread-1, handling exception: javax.net.ssl.SSLHandshakeException: no cipher suites in common
javax.net.ssl.SSLHandshakeException: no cipher suites in common
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
        at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1884)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:276)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:266)
        at sun.security.ssl.ServerHandshaker.chooseCipherSuite(ServerHandshaker.java:894)
        at sun.security.ssl.ServerHandshaker.clientHello(ServerHandshaker.java:622)
        at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:167)
        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868)
        at sun.security.ssl.Handshaker.process_record(Handshaker.java:804)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1016)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
        at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:882)
        at sun.security.ssl.AppInputStream.read(AppInputStream.java:102)
        at java.io.InputStream.read(InputStream.java:101)
        at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1792)
        at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1769)
        at org.apache.commons.io.IOUtils.copy(IOUtils.java:1744)
        at org.apache.commons.io.IOUtils.toByteArray(IOUtils.java:462)
        at com.myserver.Listener$ListenerThread.run(Listener.java:88)

客户端代码:

private static SSLSocket getSecureSocket() throws IOException 
    if (sslSocketFactory == null) 
        try 

            KeyStore truststore = KeyStore.getInstance("BKS");
            truststore.load(mTruststoreInputStream, STORES_PASSWORD.toCharArray());

            TrustManagerFactory trustManagerFactory = TrustManagerFactory.
                    getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(truststore);

            KeyStore keystore = KeyStore.getInstance("BKS");
            keystore.load(mKeystoreInputStream, STORES_PASSWORD.toCharArray());

            KeyManagerFactory keyManagerFactory = KeyManagerFactory.
                    getInstance(KeyManagerFactory.getDefaultAlgorithm());
            keyManagerFactory.init(keystore, STORES_PASSWORD.toCharArray());


            sslSocketFactory = new SSLSocketFactory(SSLSocketFactory.TLS, 
                    keystore, STORES_PASSWORD, truststore, null, null);
         catch (KeyStoreException e) 
            e.printStackTrace();
            return null;
         catch (CertificateException e ) 
            e.printStackTrace();
            return null;
         catch (NoSuchAlgorithmException e) 
            e.printStackTrace();
            return null;
         catch (IOException e) 
            e.printStackTrace();
            return null;
         catch (UnrecoverableKeyException e) 
            e.printStackTrace();
            return null;
             catch (KeyManagementException e) 
                e.printStackTrace();
                return null;
            

            
    SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket();
            Log.d(TAG, "Trying to connect socket to " + IP + " on port " + PORT + ".");
            socket.connect(new InetSocketAddress(IP, PORT));
            return socket;
public static void test() 
        new AsyncTask<Void, Void, Void>() 

            @Override
            protected Void doInBackground(Void... arg0) 
                try 
                    SSLSocket socket = getSecureSocket();
                    OutputStream os = socket.getOutputStream();
                    String data = "A big step for man, a small step for mankind";
                    byte[] bytes = data.getBytes();
                    os.write(bytes);
                 catch (IOException e) 
                    e.printStackTrace();
                
                return null;
            

        .execute();
    

服务器代码:

public SSLServerSocket createServerSocket() 
        try 
            KeyStore keystore = KeyStore.getInstance("JKS");
            FileInputStream keystoreInputStream = new FileInputStream(KEYSTORE_NAME);
            keystore.load(keystoreInputStream, STORES_PASSWORD.toCharArray());
            KeyStore truststore = KeyStore.getInstance("JKS");
            FileInputStream truststoreInputStream = new FileInputStream(TRUSTSTORE_NAME);
            truststore.load(truststoreInputStream, STORES_PASSWORD.toCharArray());
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX", "SunJSSE");
            trustManagerFactory.init(truststore);
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509", "SunJSSE");
            keyManagerFactory.init(keystore, STORES_PASSWORD.toCharArray());
            X509ExtendedKeyManager x509KeyManager = null;
            for (KeyManager keyManager : keyManagerFactory.getKeyManagers()) 
                if (keyManager instanceof X509KeyManager) 
                    x509KeyManager = (X509ExtendedKeyManager) keyManager;
                    break;
                
            
            if (x509KeyManager == null) 
                debug("Searched for x509 key managers but found none.");
                throw new NullPointerException();
            
            X509ExtendedTrustManager x509TrustManager = null;
            for (TrustManager trustManager : trustManagerFactory.getTrustManagers()) 
                if (trustManager instanceof X509TrustManager) 
                    x509TrustManager = (X509ExtendedTrustManager) trustManager;
                
            
            if (x509TrustManager == null) 
                debug("Searched for x509 trust managers but found none.");
                throw new NullPointerException();
            
            SSLContext sslContext = SSLContext.getInstance("TLS");
            KeyManager[] keyManagers =  x509KeyManager ;
            TrustManager[] trustManagers =  x509TrustManager ;
            sslContext.init(keyManagers, trustManagers, null);
            SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();
            SSLServerSocket serverSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(PORT);
            serverSocket.setNeedClientAuth(true);
            /* Force TLS 1.0, this will disable i.e SSL2 which is insecure. */
            //serverSocket.setEnabledProtocols(new String[]  "TLSv1" );
            return serverSocket;
         catch (NullPointerException e) 
            e.printStackTrace();
         catch (FileNotFoundException e) 
            e.printStackTrace();
         catch (NoSuchAlgorithmException e) 
            e.printStackTrace();
         catch (NoSuchProviderException e) 
            e.printStackTrace();
         catch (UnrecoverableKeyException e) 
            e.printStackTrace();
         catch (KeyStoreException e) 
            e.printStackTrace();
         catch (CertificateException e) 
            e.printStackTrace();
         catch (IOException e) 
            e.printStackTrace();
         catch (KeyManagementException e) 
            e.printStackTrace();
        
        return null;
    

while (true) 
    try 
        debug("Listening for incoming connections...");
        SSLSocket clientSocket = (SSLSocket) serverSocket.accept();
        // Handle connection in a separate thread.
        ListenerThread thread = new ListenerThread(clientSocket);
        thread.start();
     catch (IOException e) 
        e.printStackTrace();
    

我生成的证书如下:

使用 openssl 生成我的密钥:

openssl genrsa -des3 -out client_key.pem 4096
openssl genrsa -des3 -out client_key.pem 4096

企业社会责任:

openssl req -new -x509 -key client_key.pem -out client_cert.pem -days 365
openssl req -new -x509 -key server_key.pem -out server_cert.pem -days 365

使用 portecle 转换为 bks。 首先,打开 portecle 并创建一个新的 bks 文件。导入 server_cert.pem 和 保存为 truststore.bks。接下来,结合客户端证书和密钥文件

cat client_cert.pem client_key.pem > client.pem

使用 openssl 生成 pkcs12 文件

openssl pkcs12 -export -in client.pem -out client.pkcs12 -name "client"

在 portecle 中创建了一个新的 bks 文件。导入client.pkcs12并另存为 client.bks(这是我的服务器密钥库)。

这两个文件被导入到Android项目中,从/res/raw中加载

服务器证书是以相同的方式创建的,但我使用 portecle 来导出为 jks。 服务器密钥库包含 server.pkcs12,服务器信任库包含客户端证书 (client_cert.pem)。

任何帮助将不胜感激!

【问题讨论】:

此代码无法编译。真正的代码是什么? 这是来自 Eclipse 的复制粘贴,删除了一些调试打印。编译器是怎么说的? 与其迭代您从 KM 工厂获得的 KeyManagers,不如将 keyManagerFactory.getKeyManagers() 的结果直接传递给 SSLContext.init(...),因为它会在内部完成您的工作无论如何都想去做。 TMF 也一样。它不应该改变太多,但这会使代码更具可读性。虽然强制 TLS 或更高版本是个好主意,但 Sun/Oracle JRE 不支持 SSLv2,只支持 SSLv2Hello(w.r.t. 该行上方的注释)。 test() 方法之前的客户端代码是未终止的方法。 为什么生成了两次客户端密钥?为什么不生成服务器密钥? 【参考方案1】:

只有在以下情况下才会发生这种情况:

服务器上没有可用的私钥,或者 一端或另一端更改启用的密码套件。简单的解决方案是不要这样做。

使用相同的文件作为密钥库和信任库开始变得没有意义。一个包含私人信息,另一个包含公共信息。它们不会混合。

您的客户端代码可能无法在创建的第一个 SSLSocket 之后工作,因为它会尝试从已读取的输入流中加载密钥库和信任库。您应该有一个调用一次的方法来创建一个SSLContext,然后直接从中获取您的SSLSockets

【讨论】:

以上是关于如何修复 javax.net.ssl.SSLHandshakeException:没有共同的密码套件? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何修复 npm 审计修复问题?

如何修复drv?

如何修复漏洞

如何修复WMI

PHP网站漏洞怎么修复 如何修补网站程序代码漏洞

如何修复这些漏洞? (npm audit fix 无法修复这些漏洞)