Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何配置JDK1.6以与仅TLS服务器进行ssl握手_Java_Ssl - Fatal编程技术网

Java 如何配置JDK1.6以与仅TLS服务器进行ssl握手

Java 如何配置JDK1.6以与仅TLS服务器进行ssl握手,java,ssl,Java,Ssl,我看到客户端在JDK1.6上运行时握手失败。如何配置JDK1.6以允许客户端连接 我怀疑问题是SSLv2客户机hello或不支持的密码,但无法100%确定是哪种密码 客户端调试输出: Allow legacy hello messages: true Is initial handshake: true Is secure renegotiation: false Client, setSoTimeout(61000) called %% No cached client session ***

我看到客户端在JDK1.6上运行时握手失败。如何配置JDK1.6以允许客户端连接

我怀疑问题是SSLv2客户机hello或不支持的密码,但无法100%确定是哪种密码

客户端调试输出:

Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
Client, setSoTimeout(61000) called
%% No cached client session
*** ClientHello, TLSv1
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_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]
***
Client, WRITE: TLSv1 Handshake, length = 75
Client, WRITE: SSLv2 client hello message, length = 101
Client, received EOFException: error
Client, handling exception: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
Client
, SEND TLSv1 ALERT:  
fatal, 
description = handshake_failure

我知道另一种方法(不理想)是在远程服务器上允许SSLv2Hello伪协议。我会羞愧地低下头,要求提供商允许SSLv2Hello,但我不确定这是否会允许基于可用密码的连接成功。

由于安全问题(CVE-2014-3566或Poodle等),SSLv2和SSLv3是不推荐的协议,因此强制服务器接受它不是一个好主意

也没有必要将客户机的JVM升级到6(只要服务器接受TLSv1),您只需在创建自定义套接字工厂时禁用上述协议(扩展默认的
SSLSocketFactory
),然后在创建套接字时将其删除并设置启用的协议即可

private Socket removeSSLv2v3(Socket socket) {

    if (!(socket instanceof SSLSocket)) {
        return socket;
    }

    SSLSocket sslSocket = (SSLSocket) socket;

    String[] protocols = sslSocket.getEnabledProtocols();
    Set<String> set = new HashSet<String>();
    for (String s : protocols) {
        if (s.equals("SSLv3") || s.equals("SSLv2Hello")) {
            continue;
        }
        set.add(s);
    }
    sslSocket.setEnabledProtocols(set.toArray(new String[0]));

    return sslSocket;
}
或者,您可以在执行客户机时通过命令行中的属性设置启用的协议(对于Java 6,它只接受TLSv1)

java-Dhttps.protocols=“TLSv1”

java-Dhttps.protocols=TLSv1

不幸的是,运行时框架是封闭源代码的,否则我相信我可以使用提供的示例使其工作。我试着在startup命令中设置-Dhttps.protocols系统属性,其中我还设置了-Djavax.net.debug,但SSLv2Hello仍然存在,然后您可以将Java版本更新到6以运行客户端,Java 7默认使用TLSv1,Java 8使用TLSv1.2我不确定“将Java版本更新到6以运行客户端”是什么意思-我已经在运行1.6了。我使用JDK1.7成功地进行了测试,它选择了TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA-这个密码在Java 6中受支持吗-如果他们启用SSLv2Hello,它会在1.6客户端工作吗?抱歉,语言错误,我的意思是“最多6”大于6。Java 6支持TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,如果服务器端接受SSLv2Hello,它将起作用,但它是一个不推荐使用的(且不安全的)协议,所以保留Java 7是最好的选择。服务器现在启用了SSLv2Hello,我可以从ssllabs报告中看到SSL 2握手兼容性:是-但是握手仍然会因EOFEException而失败。ssllabs报告显示:Java6U45脚注:无SNI2服务器闭合连接,其中脚注2为:不支持虚拟SSL主机(SNI)。如果服务器使用SNI,则连接到默认站点。有什么想法吗?假设存在
$JAVA\u HOME/lib/security/JAVA.security
文件中的
jdk.tls.disabledAlgorithms
的值是多少?您可以在那里禁用SSLv2Hello和SSLv3。如果您共享同一虚拟机,您可能会中断另一个正在运行的应用程序,更改java.security默认值不是一个好主意。@vzamanillo修改配置文件(该文件存在以进行修改,以便在需要时更改配置)更可靠,与在源代码不可用的遗留应用程序中强制安装自定义代码相比,速度更快,所需的人力更少,成本更低。“更多代码”并不是每个问题的解决方案-事实上,“更多代码”通常是最不可靠和最昂贵的选项。我并不完全同意,但这是另一个讨论。作为记录,在java.security中添加jdk.tls.disabledAlgorithms=SSLv2Hello并没有阻止发送SSLv2客户端hello消息。
SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
sslContextBuilder.loadTrustMaterial(null, new TrustSelfSignedStrategy());

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContextBuilder.build(), new String[] { "TLSv1" }, null,
SSLConnectionSocketFactory.getDefaultHostnameVerifier());

CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
java -Dhttps.protocols="TLSv1" <MyClient>
java -Dhttps.protocols=TLSv1 <MyClient>