【问题标题】:How to solve "no cipher suites in common" during SSL Handshake?SSL握手期间如何解决“没有共同的密码套件”?
【发布时间】:2017-10-07 15:27:56
【问题描述】:

我正在通过 Tomcat 8 + Java 8 构建 B2B 服务。 但是我的一位客户无法使用 SSL 连接到我的服务。 添加 SSL 调试参数:“-Djavax.net.debug=ssl”后,我看到错误消息:

Is initial handshake: true
Is secure renegotiation: false
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 for TLSv1.1
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 for TLSv1.1
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
https-jsse-nio-8445-exec-9, READ: SSLv3 Handshake, length = 62
*** ClientHello, TLSv1
RandomCookie:  GMT: 1490342314 bytes = { 192, 161, 228, 31, 66, 175, 222, 13, 79, 128, 217, 81, 18, 152, 169, 58, 114, 35, 201, 201, 147, 74, 131, 2, 213, 145, 181, 76 }
Session ID:  {}
Cipher Suites: [SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, Unknown 0xff:0x3, SSL_RSA_WITH_RC4_128_MD5]
Compression Methods:  { 0 }
Extension renegotiation_info, renegotiated_connection: <empty>
***
%% Initialized:  [Session-7, SSL_NULL_WITH_NULL_NULL]
https-jsse-nio-8445-exec-9, fatal error: 40: no cipher suites in common
javax.net.ssl.SSLHandshakeException: no cipher suites in common

如何解决错误?

【问题讨论】:

    标签: java tomcat ssl


    【解决方案1】:

    这是我解决问题的经验分享。

    1. 启用 SSL 调试参数“-Djavax.net.debug=ssl”,发现错误为“no cipher suites in common”

    2. 在谷歌搜索了一些页面后,我安装了“Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction”http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html,它在 JVM 级别添加了一些密码算法,例如:TLS_RSA_WITH_AES_256_CBC_SHA,但它没有解决问题. PS。 Ciphers.java 是一个有用的代码,它可以显示 JVM 级别的可用密码套件。

    3. 我抓到网络包在wireshark中分析,客户端发送ClientHello后,我的服务器立即断开连接。

    4. 由于我的客户不能用我的测试,我必须自己重现问题以加快故障排除过程。然后我找到了代码 SslPoke.java 并对其进行了修改。它可以通过使用 TLS 版本或密码套件的不同组合来模拟客户端的请求。而且我可以自己模拟相同的错误日志,帮助很大。

    5. 然后,再次google,我发现我可以在Tomcat的server.xml中指定密码套件,例如:

    &lt;Connector port="${https.port}" SSLEnabled="true" scheme="https" sslProtocol="TLS" ciphers="TLS_RSA_WITH_AES_256_CBC_SHA256... " /&gt;

    我添加了配置,通过SslPoke测试并通过,案例关闭。

    希望经验可以帮助面临同样问题的其他人。 不要忘记检查 JVM / Web 容器 / 应用服务器中的密码套件配置... 而且下面的代码也很有用,感谢提供这些代码的专家。

    最好的问候,
    里昂

    代码:Ciphers.java,发现自:https://confluence.atlassian.com/bitbucketserverkb/list-ciphers-used-by-jvm-779171661.html

    public class Ciphers
    {
        public static void main(String[] args)
            throws Exception
        {
            SSLServerSocketFactory ssf = (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
    
            String[] defaultCiphers = ssf.getDefaultCipherSuites();
            String[] availableCiphers = ssf.getSupportedCipherSuites();
    
            TreeMap ciphers = new TreeMap();
    
            for(int i=0; i<availableCiphers.length; ++i )
                ciphers.put(availableCiphers[i], Boolean.FALSE);
    
            for(int i=0; i<defaultCiphers.length; ++i )
                ciphers.put(defaultCiphers[i], Boolean.TRUE);
    
            System.out.println("Default\tCipher");
            for(Iterator i = ciphers.entrySet().iterator(); i.hasNext(); ) {
                Map.Entry cipher=(Map.Entry)i.next();
    
                if(Boolean.TRUE.equals(cipher.getValue()))
                    System.out.print('*');
                else
                    System.out.print(' ');
    
                System.out.print('\t');
                System.out.println(cipher.getKey());
            }
        }
    }
    

    代码:SslPoke.java,发现自:https://gist.github.com/4ndrej/4547029

    public class SslPoke {
    
        private static javax.net.ssl.SSLSocketFactory getFactorySimple() throws Exception {
            SSLContext context = SSLContext.getInstance("TLSv1");
    
            context.init(null, null, null);
    
            return context.getSocketFactory();
    
        }
    
        public static void main(String[] args) {
            System.getProperties().setProperty("javax.net.debug", "ssl");
            System.getProperties().setProperty("https.cipherSuites", "TLS_RSA_WITH_AES_256_CBC_SHA");
    
            try {
                String urlStr ="https://<your host>:<your port>";
                URL url = new URL(urlStr);
    
                HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
    
                javax.net.ssl.SSLSocketFactory sslSocketFactory = getFactorySimple();
    
                connection.setSSLSocketFactory(sslSocketFactory);
                InputStream in = connection.getInputStream();
    
                while (in.available() > 0) {
                    System.out.print(in.read());
                }
                System.out.println("Successfully connected");
    
            } catch (Exception exception) {
                exception.printStackTrace();
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-12-02
      • 1970-01-01
      • 1970-01-01
      • 2018-01-31
      • 1970-01-01
      • 2017-12-17
      • 2020-01-07
      • 2015-09-25
      • 2019-07-11
      相关资源
      最近更新 更多