SSLHandshakeException:在 tomcat 7 服务器上设置密码时收到致命警报:handshake_failure [英] SSLHandshakeException: Received fatal alert: handshake_failure when setting ciphers on tomcat 7 server

查看:49
本文介绍了SSLHandshakeException:在 tomcat 7 服务器上设置密码时收到致命警报:handshake_failure的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 Tomcat7 网络服务器,我试图通过将此连接器添加到 server.xml 文件来将其配置为接受安全连接:

<连接器 SSLEnabled="true"acceptCount="100"连接超时=20000"executor="tomcatThreadPool"keyAlias="服务器"keystoreFile="c:optengineconf	c.keystore"keystorePass="o39UI12z"maxKeepAliveRequests="15"端口=8443"协议="HTTP/1.1"重定向端口 =8443"方案=https"安全=真"sslProtocol="TLS"/>

我使用的是使用此命令生成的自签名证书:

%JAVA_HOME%/bin/keytool -genkeypair -keystore c:optengineconf	c.keystore -storepass o39UI12z-keypass o39UI12z-dname "cn=Company, ou=Company, o=Com,c=US" -别名服务器 -validity 36500

在客户端,我有一个使用 RestTemplate 与服务器连接的 spring 应用程序.在应用程序上下文启动时,我以这种方式初始化 restTemplate 实例:

final ClientHttpRequestFactory clientHttpRequestFactory =new MyCustomClientHttpRequestFactory(new NullHostNameVerifier(), serverInfo);restTemplate.setRequestFactory(clientHttpRequestFactory);

类 MyCustomClientHttpRequestFactory 如下所示:

public class MyCustomClientHttpRequestFactory 扩展 SimpleClientHttpRequestFactory {私有静态最终记录器 LOGGER = LoggerFactory.getLogger(MyCustomClientHttpRequestFactory.class);私有最终 HostnameVerifier hostNameVerifier;私有最终 ServerInfo serverInfo;public MyCustomClientHttpRequestFactory (final HostnameVerifier hostNameVerifier,最终的 ServerInfo serverInfo) {this.hostNameVerifier = hostNameVerifier;this.serverInfo = serverInfo;}@覆盖受保护的无效准备连接(最终的 HttpURLConnection 连接,最终的字符串 httpMethod)抛出 IOException {如果(HttpsURLConnection 的连接实例){((HttpsURLConnection) 连接).setHostnameVerifier(hostNameVerifier);((HttpsURLConnection) 连接).setSSLSocketFactory(initSSLContext().getSocketFactory());}super.prepareConnection(connection, httpMethod);}私有 SSLContext initSSLContext() {尝试 {System.setProperty("https.protocols", "TLSv1");//设置 ssl 信任管理器.根据我们的服务器指纹进行验证最终 SSLContext ctx = SSLContext.getInstance("TLSv1");最终 SslThumbprintVerifier 验证器 = 新 SslThumbprintVerifier(serverInfo);最后的 ThumbprintTrustManager thumbPrintTrustManager =新 ThumbprintTrustManager(null, verifier);ctx.init(null, new TrustManager[] { thumbPrintTrustManager }, null);返回ctx;} 捕获(最终异常前){LOGGER.error(尝试初始化 HTTP 安全管理器时抛出异常.", ex);返回空;}}

直到这里一切正常.当我在 SslThumbprintVerifier 类中放置一个断点时,代码到达了这一点,也到达了 NullHostNameVerifier 类.这已经在生产中进行了测试,效果很好.

现在我想通过限制密码套件来扩展安全性,我将此属性添加到我在开头介绍的连接器中:

 <代码>密码= TLS_KRB5_WITH_RC4_128_SHA,SSL_RSA_WITH_RC4_128_SHA,SSL_DHE_RSA_WITH_AES_256_CBC_SHA,SSL_RSA_WITH_AES_256_CBC_SHA,SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,SSL_RSA_WITH_3DES_EDE_CBC_SHA,SSL_DHE_RSA_WITH_AES_128_CBC_SHA,SSL_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_RC4_128_SHA,TLS_RSA_WITH_3DES_EDE_CBC_SHA,TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_RSA_WITH_AES_256_CBC_SHA,TLS_KRB5_WITH_3DES_EDE_CBC_SHA"

现在,当我运行客户端代码时,出现此异常:

javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure

这发生在 restTemplate.doExecute() 方法中.代码不会像添加密码之前那样到达指纹验证器类和主机名验证器类.

在调试中我检查了 ctx.getSocketFactory().getSupportedCipherSuites() 显示:

<预> <代码> [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_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,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,SSL_RSA_WITH_NULL_MD5,SSL_RSA_WITH_NULL_SHA,SSL_DH_anon_WITH_RC4_128_MD5,TLS_DH_anon_WITH_AES_128_CBC_SHA,TLS_DH_anon_WITH_AES_256_CBC_SHA,SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,SSL_DH_anon_WITH_DES_CBC_SHA,SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,TLS_KRB5_WITH_RC4_128_SHA,TLS_KRB5_WITH_RC4_128_MD5,TLS_KRB5_WITH_3DES_EDE_CBC_SHA,TLS_KRB5_WITH_3DES_EDE_CBC_MD5,TLS_KRB5_WITH_DES_CBC_SHA,TLS_KRB5_WITH_DES_CBC_MD5,TLS_KRB5_EXPORT_WITH_RC4_40_SHA,TLS_KRB5_EXPORT_WITH_RC4_40_MD5,TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA,TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5]

并且还检查了ctx.getSocketFactory().getDefaultCipherSuites():

<预> <代码> [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_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,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]

最后是 ctx.getSupportedSSLParameters().getCipherSuites():

<预> <代码> [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_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,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,SSL_RSA_WITH_NULL_MD5,SSL_RSA_WITH_NULL_SHA,SSL_DH_anon_WITH_RC4_128_MD5,TLS_DH_anon_WITH_AES_128_CBC_SHA,TLS_DH_anon_WITH_AES_256_CBC_SHA,SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,SSL_DH_anon_WITH_DES_CBC_SHA,SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,TLS_KRB5_WITH_RC4_128_SHA,TLS_KRB5_WITH_RC4_128_MD5,TLS_KRB5_WITH_3DES_EDE_CBC_SHA,TLS_KRB5_WITH_3DES_EDE_CBC_MD5,TLS_KRB5_WITH_DES_CBC_SHA,TLS_KRB5_WITH_DES_CBC_MD5,TLS_KRB5_EXPORT_WITH_RC4_40_SHA,TLS_KRB5_EXPORT_WITH_RC4_40_MD5,TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA,TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5]

据我所知,如果客户端支持/启用的密码套件与服务器支持的密码套件之间存在交集,它应该可以工作(例如,我们与 SSL_RSA_WITH_RC4_128_SHA 有这样的交集).然而我收到了这个错误.

在下一步中,我添加了这个 java 参数:

-Djavax.net.debug=ssl,handshake,failure

日志只显示客户端问候,没有服务器问候响应:

<前><代码>[2013-03-20 15:29:51.315] [INFO] data-service-pool-37 System.out 触发 SecureRandom 的种子[2013-03-20 15:29:51.315] [INFO] data-service-pool-37 System.out 完成播种 SecureRandom[2013-03-20 15:30:38.894] [INFO] data-service-pool-37 System.out 允许不安全的重新协商:false[2013-03-20 15:30:38.894] [INFO] data-service-pool-37 System.out 允许旧的 hello 消息:true[2013-03-20 15:30:38.894] [INFO] data-service-pool-37 System.out 是初始握手:true[2013-03-20 15:30:38.894] [INFO] data-service-pool-37 System.out 是否安全重新协商:false[2013-03-20 15:30:38.894] [INFO] data-service-pool-37 System.out %% 没有缓存的客户端会话[2013-03-20 15:30:38.894] [INFO] data-service-pool-37 System.out *** ClientHello, TLSv1[2013-03-20 15:30:38.941] [INFO] data-service-pool-37 System.out RandomCookie: GMT: 1363720446 bytes = { 99, 249, 173, 214, 110, 82, 58, 51892, 92, 74, 169, 133, 128, 250, 109, 160, 64, 112, 253, 50, 160, 255, 196, 85, 93, 33, 172 }[2013-03-20 15:30:38.941] [INFO] data-service-pool-37 System.out 会话 ID:{}[2013年3月20日15:30:38.941] [INFO]数据服务池-37的System.out密码套件:[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_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,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][2013-03-20 15:30:38.956] [INFO] data-service-pool-37 System.out 压缩方法:{0}[2013-03-20 15:30:38.956] [INFO] data-service-pool-37 System.out ***[2013-03-20 15:30:38.956] [INFO] data-service-pool-37 System.out data-service-pool-37, WRITE: TLSv1 Handshake, length = 81[2013-03-20 15:30:38.956] [INFO] data-service-pool-37 System.out data-service-pool-37, READ: TLSv1 Alert, length = 2[2013-03-20 15:30:38.956] [INFO] data-service-pool-37 System.out data-service-pool-37, RECV TLSv1 ALERT: 致命,handshake_failure[2013-03-20 15:30:38.972] [INFO] data-service-pool-37 System.out data-service-pool-37,称为 closeSocket()[2013-03-20 15:30:38.972] [INFO] data-service-pool-37 System.out data-service-pool-37,处理异常:javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure

当从 server.xml 中删除密码时,它会再次工作.我还要提到我正在同一台机器上测试服务器和客户端.我尝试将客户端请求中的服务器 ip 设置为localhost"和实际机器 ip,但它没有在这两种情况下都不起作用.此外,我让这台服务器在不同的 linux 机器上运行(当然,密钥库是在 linux 机器上生成的,当然还有 linux 路径)并且仍然 - 它在没有密码的情况下工作并停止使用密码.

解决方案

好吧,我解决了这个问题.似乎通过使用 keytool 创建自签名证书,不提供 -keyalg 参数 使密钥对算法默认为 DSA.我的密码套件都没有包含 DSA 算法.在这种情况下,虽然客户端和服务器的密码套件有交集,但都不适合密钥算法.

在生成keystore时添加-keyalg RSA,问题解决.

I have a Tomcat7 web-server which I tried to configure to accept secure connections by adding this connector to the server.xml file:

<Connector SSLEnabled="true"
           acceptCount="100"
           connectionTimeout="20000"
           executor="tomcatThreadPool"
           keyAlias="server"
           keystoreFile="c:optengineconf	c.keystore"
           keystorePass="o39UI12z"
           maxKeepAliveRequests="15"
           port="8443"
           protocol="HTTP/1.1"
           redirectPort="8443"
           scheme="https"
           secure="true"
           sslProtocol="TLS"/>

I'm using a self-signed certificate generated using this command:

%JAVA_HOME%/bin/keytool -genkeypair -keystore c:optengineconf	c.keystore -storepass o39UI12z-keypass o39UI12z-dname "cn=Company, ou=Company, o=Com, c=US" -alias server -validity 36500

On the client side I have a spring application that connects with the server using RestTemplate. On application context startup I initalize the restTemplate instance this way:

final ClientHttpRequestFactory clientHttpRequestFactory =
        new MyCustomClientHttpRequestFactory(new NullHostNameVerifier(), serverInfo);
    restTemplate.setRequestFactory(clientHttpRequestFactory);

The class MyCustomClientHttpRequestFactory looks like this:

public class MyCustomClientHttpRequestFactory  extends SimpleClientHttpRequestFactory {

private static final Logger LOGGER = LoggerFactory
    .getLogger(MyCustomClientHttpRequestFactory.class);

private final HostnameVerifier hostNameVerifier;
private final ServerInfo serverInfo;

public MyCustomClientHttpRequestFactory (final HostnameVerifier hostNameVerifier,
    final ServerInfo serverInfo) {
    this.hostNameVerifier = hostNameVerifier;
    this.serverInfo = serverInfo;
}

@Override
protected void prepareConnection(final HttpURLConnection connection, final String httpMethod)
    throws IOException {
    if (connection instanceof HttpsURLConnection) {
        ((HttpsURLConnection) connection).setHostnameVerifier(hostNameVerifier);
        ((HttpsURLConnection) connection).setSSLSocketFactory(initSSLContext()
            .getSocketFactory());
    }
    super.prepareConnection(connection, httpMethod);
}

private SSLContext initSSLContext() {
    try {
        System.setProperty("https.protocols", "TLSv1");

        // Set ssl trust manager. Verify against our server thumbprint
        final SSLContext ctx = SSLContext.getInstance("TLSv1");
        final SslThumbprintVerifier verifier = new SslThumbprintVerifier(serverInfo);
        final ThumbprintTrustManager thumbPrintTrustManager =
            new ThumbprintTrustManager(null, verifier);
        ctx.init(null, new TrustManager[] { thumbPrintTrustManager }, null);
        return ctx;
    } catch (final Exception ex) {
        LOGGER.error(
            "An exception was thrown while trying to initialize HTTP security manager.", ex);
        return null;
    }
}

Up until here everything worked fine. When I put a break point in the SslThumbprintVerifier class, the code reached to this point and also to the NullHostNameVerifier class. This was tested in production and worked great.

Now I wanted to extend security by limiting the cipher suites and I added this property to the Connector I presented at the beginning:

ciphers="TLS_KRB5_WITH_RC4_128_SHA,SSL_RSA_WITH_RC4_128_SHA,SSL_DHE_RSA_WITH_AES_256_CBC_SHA,SSL_RSA_WITH_AES_256_CBC_SHA,SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,SSL_RSA_WITH_3DES_EDE_CBC_SHA,SSL_DHE_RSA_WITH_AES_128_CBC_SHA,SSL_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_RC4_128_SHA,TLS_RSA_WITH_3DES_EDE_CBC_SHA,TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_RSA_WITH_AES_256_CBC_SHA,TLS_KRB5_WITH_3DES_EDE_CBC_SHA"

Now when I'm running the client code I get this exception:

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

This happens in the restTemplate.doExecute() method. The code doesn't reach to the thumbprint verifier class nor to the host name verifier class as it did before adding the ciphers.

In debug I checked the ctx.getSocketFactory().getSupportedCipherSuites() which showed:

[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_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, 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, SSL_RSA_WITH_NULL_MD5, SSL_RSA_WITH_NULL_SHA, SSL_DH_anon_WITH_RC4_128_MD5, TLS_DH_anon_WITH_AES_128_CBC_SHA, TLS_DH_anon_WITH_AES_256_CBC_SHA, SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, SSL_DH_anon_WITH_DES_CBC_SHA, SSL_DH_anon_EXPORT_WITH_RC4_40_MD5, SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA, TLS_KRB5_WITH_RC4_128_SHA, TLS_KRB5_WITH_RC4_128_MD5, TLS_KRB5_WITH_3DES_EDE_CBC_SHA, TLS_KRB5_WITH_3DES_EDE_CBC_MD5, TLS_KRB5_WITH_DES_CBC_SHA, TLS_KRB5_WITH_DES_CBC_MD5, TLS_KRB5_EXPORT_WITH_RC4_40_SHA, TLS_KRB5_EXPORT_WITH_RC4_40_MD5, TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA, TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5]

and also checked ctx.getSocketFactory().getDefaultCipherSuites():

[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_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, 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]

and lastly the ctx.getSupportedSSLParameters().getCipherSuites():

[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_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, 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, SSL_RSA_WITH_NULL_MD5, SSL_RSA_WITH_NULL_SHA, SSL_DH_anon_WITH_RC4_128_MD5, TLS_DH_anon_WITH_AES_128_CBC_SHA, TLS_DH_anon_WITH_AES_256_CBC_SHA, SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, SSL_DH_anon_WITH_DES_CBC_SHA, SSL_DH_anon_EXPORT_WITH_RC4_40_MD5, SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA, TLS_KRB5_WITH_RC4_128_SHA, TLS_KRB5_WITH_RC4_128_MD5, TLS_KRB5_WITH_3DES_EDE_CBC_SHA, TLS_KRB5_WITH_3DES_EDE_CBC_MD5, TLS_KRB5_WITH_DES_CBC_SHA, TLS_KRB5_WITH_DES_CBC_MD5, TLS_KRB5_EXPORT_WITH_RC4_40_SHA, TLS_KRB5_EXPORT_WITH_RC4_40_MD5, TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA, TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5]

As far as I understand, if there's an intersection between the client's supported/enabled cipher suites and the server's supported cipher suites it should work (we have such intersection with SSL_RSA_WITH_RC4_128_SHA for example). And yet I'm getting this error.

In the next step I added this java parameter:

-Djavax.net.debug=ssl,handshake,failure

The log showed only the client-hello, with no server-hello response:


[2013-03-20 15:29:51.315] [INFO ] data-service-pool-37          System.out                                                        trigger seeding of SecureRandom 
[2013-03-20 15:29:51.315] [INFO ] data-service-pool-37          System.out                                                        done seeding SecureRandom 
[2013-03-20 15:30:38.894] [INFO ] data-service-pool-37          System.out                                                        Allow unsafe renegotiation: false 
[2013-03-20 15:30:38.894] [INFO ] data-service-pool-37          System.out                                                        Allow legacy hello messages: true 
[2013-03-20 15:30:38.894] [INFO ] data-service-pool-37          System.out                                                        Is initial handshake: true 
[2013-03-20 15:30:38.894] [INFO ] data-service-pool-37          System.out                                                        Is secure renegotiation: false 
[2013-03-20 15:30:38.894] [INFO ] data-service-pool-37          System.out                                                        %% No cached client session 
[2013-03-20 15:30:38.894] [INFO ] data-service-pool-37          System.out                                                        *** ClientHello, TLSv1 
[2013-03-20 15:30:38.941] [INFO ] data-service-pool-37          System.out                                                        RandomCookie:  GMT: 1363720446 bytes = { 99, 249, 173, 214, 110, 82, 58, 52, 189, 92, 74, 169, 133, 128, 250, 109, 160, 64, 112, 253, 50, 160, 255, 196, 85, 93, 33, 172 } 
[2013-03-20 15:30:38.941] [INFO ] data-service-pool-37          System.out                                                        Session ID:  {} 
[2013-03-20 15:30:38.941] [INFO ] data-service-pool-37          System.out                                                        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_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, 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] 
[2013-03-20 15:30:38.956] [INFO ] data-service-pool-37          System.out                                                        Compression Methods:  { 0 } 
[2013-03-20 15:30:38.956] [INFO ] data-service-pool-37          System.out                                                        *** 
[2013-03-20 15:30:38.956] [INFO ] data-service-pool-37          System.out                                                        data-service-pool-37, WRITE: TLSv1 Handshake, length = 81 
[2013-03-20 15:30:38.956] [INFO ] data-service-pool-37          System.out                                                        data-service-pool-37, READ: TLSv1 Alert, length = 2 
[2013-03-20 15:30:38.956] [INFO ] data-service-pool-37          System.out                                                        data-service-pool-37, RECV TLSv1 ALERT:  fatal, handshake_failure 
[2013-03-20 15:30:38.972] [INFO ] data-service-pool-37          System.out                                                        data-service-pool-37, called closeSocket() 
[2013-03-20 15:30:38.972] [INFO ] data-service-pool-37          System.out                                                        data-service-pool-37, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure 

When removing the ciphers from the server.xml it works again. Also I will mention that I'm testing both the server and the client on the same machine. I tried setting the server's ip in the client request to 'localhost' and to the actual machine ip and it didn't work in both cases. Also, I had this server running on a different linux machine (the keystore was generated on the linux machine with a linux path of course) and still - it works without the ciphers and stops working with the ciphers.

解决方案

Well, I got this issue solved. It appears that by creating a self-signed certificate, using keytool, without providing -keyalg parameter makes the key-pair algorithm default to DSA. None of my ciphers suite included DSA algorithm. In that case, although the client and the server had intersection between their cipher-suites, neither was suitable for the key algoritm.

Adding -keyalg RSA when generating the keystore, solved the problem.

这篇关于SSLHandshakeException:在 tomcat 7 服务器上设置密码时收到致命警报:handshake_failure的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆