为什么 SSL 握手给出“无法生成 DH 密钥对”?例外?

发布于 2024-11-26 19:40:33 字数 4686 浏览 1 评论 0 原文

当我与某些 IRC 服务器(但不是其他服务器 - 可能是由于服务器的首选加密方法)建立 SSL 连接时,我收到以下异常:

Caused by: java.lang.RuntimeException: Could not generate DH keypair
    at com.sun.net.ssl.internal.ssl.DHCrypt.<init>(DHCrypt.java:106)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverKeyExchange(ClientHandshaker.java:556)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:183)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593)
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:893)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1165)
    ... 3 more

最终原因:

Caused by: java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive)
    at com.sun.crypto.provider.DHKeyPairGenerator.initialize(DashoA13*..)
    at java.security.KeyPairGenerator$Delegate.initialize(KeyPairGenerator.java:627)
    at com.sun.net.ssl.internal.ssl.DHCrypt.<init>(DHCrypt.java:100)
    ... 10 more

演示此问题的服务器示例是 opening.esper.net:6697 (这是一个 IRC 服务器)。未显示该问题的服务器示例是 kornbluth.freenode.net:6697。 [毫不奇怪,每个网络上的所有服务器都具有相同的各自行为。]

我的代码(如前所述,在连接到某些 SSL 服务器时确实有效)是:

    SSLContext sslContext = SSLContext.getInstance("SSL");
    sslContext.init(null, trustAllCerts, new SecureRandom());
    s = (SSLSocket)sslContext.getSocketFactory().createSocket();
    s.connect(new InetSocketAddress(host, port), timeout);
    s.setSoTimeout(0);
    ((SSLSocket)s).startHandshake();

这是最后一个 startHandshake 抛出异常。是的,“trustAllCerts”有一些魔力;该代码强制 SSL 系统不验证证书。 (所以...不是证书问题。)

显然,一种可能性是 esper 的服务器配置错误,但我进行了搜索,没有找到任何其他关于 esper 的 SSL 端口有问题的人的引用,并且“openssl”连接到它(请参阅以下)。所以我想知道这是否是 Java 默认 SSL 支持的限制或其他什么。有什么建议吗?

这是当我从命令行使用“openssl”连接到 aperture.esper.net 6697 时发生的情况:

~ $ openssl s_client -connect aperture.esper.net:6697
CONNECTED(00000003)
depth=0 /C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/[email protected]
verify error:num=18:self signed certificate
verify return:1
depth=0 /C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/[email protected]
verify return:1
---
Certificate chain
 0 s:/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/[email protected]
   i:/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/[email protected]
---
Server certificate
-----BEGIN CERTIFICATE-----
[There was a certificate here, but I deleted it to save space]
-----END CERTIFICATE-----
subject=/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/[email protected]
issuer=/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/[email protected]
---
No client certificate CA names sent
---
SSL handshake has read 2178 bytes and written 468 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : DHE-RSA-AES256-SHA
    Session-ID: 51F1D40A1B044700365D3BD1C61ABC745FB0C347A334E1410946DCB5EFE37AFD
    Session-ID-ctx: 
    Master-Key: DF8194F6A60B073E049C87284856B5561476315145B55E35811028C4D97F77696F676DB019BB6E271E9965F289A99083
    Key-Arg   : None
    Start Time: 1311801833
    Timeout   : 300 (sec)
    Verify return code: 18 (self signed certificate)
---

如前所述,毕竟,它确实连接成功,这比您对我的 Java 应用程序所说的要多。

如果相关的话,我使用的是 OS X 10.6.8,Java 版本 1.6.0_26。

When I make an SSL connection with some IRC servers (but not others - presumably due to the server's preferred encryption method) I get the following exception:

Caused by: java.lang.RuntimeException: Could not generate DH keypair
    at com.sun.net.ssl.internal.ssl.DHCrypt.<init>(DHCrypt.java:106)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverKeyExchange(ClientHandshaker.java:556)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:183)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593)
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:893)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1165)
    ... 3 more

Final cause:

Caused by: java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive)
    at com.sun.crypto.provider.DHKeyPairGenerator.initialize(DashoA13*..)
    at java.security.KeyPairGenerator$Delegate.initialize(KeyPairGenerator.java:627)
    at com.sun.net.ssl.internal.ssl.DHCrypt.<init>(DHCrypt.java:100)
    ... 10 more

An example of a server that demonstrates this problem is aperture.esper.net:6697 (this is an IRC server). An example of a server that does not demonstrate the problem is kornbluth.freenode.net:6697. [Not surprisingly, all servers on each network share the same respective behaviour.]

My code (which as noted does work when connecting to some SSL servers) is:

    SSLContext sslContext = SSLContext.getInstance("SSL");
    sslContext.init(null, trustAllCerts, new SecureRandom());
    s = (SSLSocket)sslContext.getSocketFactory().createSocket();
    s.connect(new InetSocketAddress(host, port), timeout);
    s.setSoTimeout(0);
    ((SSLSocket)s).startHandshake();

It's that last startHandshake that throws the exception. And yes there is some magic going on with the 'trustAllCerts'; that code forces the SSL system not to validate certs. (So... not a cert problem.)

Obviously one possibility is that esper's server is misconfigured, but I searched and didn't find any other references to people having problems with esper's SSL ports, and 'openssl' connects to it (see below). So I'm wondering if this is a limitation of Java default SSL support, or something. Any suggestions?

Here's what happens when I connect to aperture.esper.net 6697 using 'openssl' from commandline:

~ $ openssl s_client -connect aperture.esper.net:6697
CONNECTED(00000003)
depth=0 /C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/[email protected]
verify error:num=18:self signed certificate
verify return:1
depth=0 /C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/[email protected]
verify return:1
---
Certificate chain
 0 s:/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/[email protected]
   i:/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/[email protected]
---
Server certificate
-----BEGIN CERTIFICATE-----
[There was a certificate here, but I deleted it to save space]
-----END CERTIFICATE-----
subject=/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/[email protected]
issuer=/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/[email protected]
---
No client certificate CA names sent
---
SSL handshake has read 2178 bytes and written 468 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : DHE-RSA-AES256-SHA
    Session-ID: 51F1D40A1B044700365D3BD1C61ABC745FB0C347A334E1410946DCB5EFE37AFD
    Session-ID-ctx: 
    Master-Key: DF8194F6A60B073E049C87284856B5561476315145B55E35811028C4D97F77696F676DB019BB6E271E9965F289A99083
    Key-Arg   : None
    Start Time: 1311801833
    Timeout   : 300 (sec)
    Verify return code: 18 (self signed certificate)
---

As noted, after all that, it does connect successfully which is more than you can say for my Java app.

Should it be relevant, I'm using OS X 10.6.8, Java version 1.6.0_26.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(22

┊风居住的梦幻卍 2024-12-03 19:40:34

您的 Maven 依赖项可能不正确。
您必须在 Maven 依赖项层次结构中找到这些库:

bcprov-jdk14, bcpkix-jdk14, bcmail-jdk14

如果您有这些依赖项,那就是错误,您应该执行以下操作:

添加依赖项:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcmail-jdk15on</artifactId>
    <version>1.59</version>
</dependency>

从包含错误依赖项的工件中排除这些依赖项,在我的例子中是:

<dependency>
    <groupId>com.lowagie</groupId>
    <artifactId>itext</artifactId>
    <version>2.1.7</version>
    <exclusions>
        <exclusion>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bctsp-jdk14</artifactId>                
        </exclusion>
        <exclusion>
            <groupId>bouncycastle</groupId>
            <artifactId>bcprov-jdk14</artifactId>               
        </exclusion>
        <exclusion>
            <groupId>bouncycastle</groupId>
            <artifactId>bcmail-jdk14</artifactId>               
        </exclusion>
    </exclusions>       
</dependency>

It is possible that you have incorrect Maven dependencies.
You must find these libraries in Maven dependency hierarchy:

bcprov-jdk14, bcpkix-jdk14, bcmail-jdk14

If you have these dependencies that is the error, and you should do this:

Add the dependency:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcmail-jdk15on</artifactId>
    <version>1.59</version>
</dependency>

Exclude these dependencies from the artifact that included the wrong dependencies, in my case it is:

<dependency>
    <groupId>com.lowagie</groupId>
    <artifactId>itext</artifactId>
    <version>2.1.7</version>
    <exclusions>
        <exclusion>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bctsp-jdk14</artifactId>                
        </exclusion>
        <exclusion>
            <groupId>bouncycastle</groupId>
            <artifactId>bcprov-jdk14</artifactId>               
        </exclusion>
        <exclusion>
            <groupId>bouncycastle</groupId>
            <artifactId>bcmail-jdk14</artifactId>               
        </exclusion>
    </exclusions>       
</dependency>
差↓一点笑了 2024-12-03 19:40:34

如果您使用的是jdk1.7.0_04,请升级到jdk1.7.0_21。该问题已在该更新中得到解决。

If you are using jdk1.7.0_04, upgrade to jdk1.7.0_21. The problem has been fixed in that update.

生寂 2024-12-03 19:40:34

尝试从 下载“Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files” Java 下载站点 并替换 JRE 中的文件。

这对我有用,我什至不需要使用 BouncyCastle - 标准 Sun JCE 能够连接到服务器。

附言。当我在更改策略文件之前尝试使用 BouncyCastle 时,出现了相同的错误 (ArrayIndexOutOfBoundsException: 64),所以看起来我们的情况非常相似。

Try downloading "Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files" from the Java download site and replacing the files in your JRE.

This worked for me and I didn't even need to use BouncyCastle - the standard Sun JCE was able to connect to the server.

PS. I got the same error (ArrayIndexOutOfBoundsException: 64) when I tried using BouncyCastle before changing the policy files, so it seems our situation is very similar.

情徒 2024-12-03 19:40:34

如果您仍然被这个问题困扰并且您正在使用 Apache httpd v> 2.4.7,试试这个: http://httpd.apache.org/ docs/current/ssl/ssl_faq.html#javadh

从 url 复制

从版本 2.4.7 开始,mod_ssl 将使用 DH 参数其中包括长度超过 1024 位的素数。然而,Java 7 及更早版本将对 DH 素数大小的支持限制为最大 1024 位。

如果您的基于 Java 的客户端因异常而中止,例如 java.lang.RuntimeException: Could not generated DH keypair 和 java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (included),并且httpd 记录 tlsv1 警报内部错误(SSL 警报编号 80)(LogLevel 信息或更高),您可以重新排列 mod_ssl密码列表与 SSLCipherSuite(可能与 SSLHonorCipherOrder 结合使用),或者您可以使用带有 1024 位素数的自定义 DH 参数,该参数始终优先于任何内置 DH 参数。

要生成自定义 DH 参数,请使用

openssl dhparam 1024

命令。或者,您可以使用 RFC 2409 第 6.2 节中的以下标准 1024 位 DH 参数:

-----BEGIN DH PARAMETERS-----
MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR
Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL
/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC
-----END DH PARAMETERS-----

将自定义参数(包括“BEGIN DH PARAMETERS”和“END DH PARAMETERS”行)添加到您配置的第一个证书文件的末尾SSLCertificateFile 指令。


我在客户端使用java 1.6,它解决了我的问题。我没有降低密码套件等,而是将自定义生成的 DH 参数添加到证书文件中。

If you are still bitten by this issue AND you are using Apache httpd v> 2.4.7, try this: http://httpd.apache.org/docs/current/ssl/ssl_faq.html#javadh

copied from the url:

Beginning with version 2.4.7, mod_ssl will use DH parameters which include primes with lengths of more than 1024 bits. Java 7 and earlier limit their support for DH prime sizes to a maximum of 1024 bits, however.

If your Java-based client aborts with exceptions such as java.lang.RuntimeException: Could not generate DH keypair and java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive), and httpd logs tlsv1 alert internal error (SSL alert number 80) (at LogLevel info or higher), you can either rearrange mod_ssl's cipher list with SSLCipherSuite (possibly in conjunction with SSLHonorCipherOrder), or you can use custom DH parameters with a 1024-bit prime, which will always have precedence over any of the built-in DH parameters.

To generate custom DH parameters, use the

openssl dhparam 1024

command. Alternatively, you can use the following standard 1024-bit DH parameters from RFC 2409, section 6.2:

-----BEGIN DH PARAMETERS-----
MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR
Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL
/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC
-----END DH PARAMETERS-----

Add the custom parameters including the "BEGIN DH PARAMETERS" and "END DH PARAMETERS" lines to the end of the first certificate file you have configured using the SSLCertificateFile directive.


I am using java 1.6 on client side, and it solved my issue. I didn't lowered the cipher suites or like, but added a custom generated DH param to the cert file..

-小熊_ 2024-12-03 19:40:34

我对 Yandex Maps 服务器、JDK 1.6 和 Apache HttpClient 4.2.1 也有同样的问题。该错误是

javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

-Djavax.net.debug=all 启用调试引起的,日志中有一条消息

Could not generate DH keypair

我已通过添加 BouncyCastle 库 bcprov-jdk16-1.46.jar 修复了此问题code> 并在地图服务类中注册提供程序

public class MapService {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    public GeocodeResult geocode() {

    }

}

第一次使用MapService 时会注册提供程序。

I have the same problem with Yandex Maps server, JDK 1.6 and Apache HttpClient 4.2.1. The error was

javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

with enabled debug by -Djavax.net.debug=all there was a message in a log

Could not generate DH keypair

I have fixed this problem by adding BouncyCastle library bcprov-jdk16-1.46.jar and registering a provider in a map service class

public class MapService {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    public GeocodeResult geocode() {

    }

}

A provider is registered at the first usage of MapService.

不乱于心 2024-12-03 19:40:34

我在运行 JDK 6 的 CentOS 服务器上遇到 SSL 错误。

我的计划是安装更高版本的 JDK (JDK 7) 以与 JDK 6 共存,但事实证明,只需使用 rpm -i 安装较新的 JDK 还不够。

只有使用 rpm -U 升级选项才能成功安装 JDK 7,如下所示。

1.下载JDK 7

wget -O /root/jdk-7u79-linux-x64.rpm --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; o raclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/7u79-b15/jdk-7u79-linux-x64.rpm"

2.RPM安装失败

rpm -ivh jdk-7u79-linux-x64.rpm
Preparing...                ########################################### [100%]
        file /etc/init.d/jexec from install of jdk-2000:1.7.0_79-fcs.x86_64 conflicts with file from package jdk-2000:1.6.0_43-fcs.x86_64

3.RPM升级成功

rpm -Uvh jdk-7u79-linux-x64.rpm
Preparing...                ########################################### [100%]
   1:jdk                    ########################################### [100%]
Unpacking JAR files...
        rt.jar...
        jsse.jar...
        charsets.jar...
        tools.jar...
        localedata.jar...
        jfxrt.jar...

4.确认新版本

java -version
java version "1.7.0_79"
Java(TM) SE Runtime Environment (build 1.7.0_79-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode)

I encountered the SSL error on a CentOS server running JDK 6.

My plan was to install a higher JDK version (JDK 7) to co-exist with JDK 6 but it turns out that merely installing the newer JDK with rpm -i was not enough.

The JDK 7 installation would only succeed with the rpm -U upgrade option as illustrated below.

1. Download JDK 7

wget -O /root/jdk-7u79-linux-x64.rpm --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; o raclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/7u79-b15/jdk-7u79-linux-x64.rpm"

2. RPM installation fails

rpm -ivh jdk-7u79-linux-x64.rpm
Preparing...                ########################################### [100%]
        file /etc/init.d/jexec from install of jdk-2000:1.7.0_79-fcs.x86_64 conflicts with file from package jdk-2000:1.6.0_43-fcs.x86_64

3. RPM upgrade succeeds

rpm -Uvh jdk-7u79-linux-x64.rpm
Preparing...                ########################################### [100%]
   1:jdk                    ########################################### [100%]
Unpacking JAR files...
        rt.jar...
        jsse.jar...
        charsets.jar...
        tools.jar...
        localedata.jar...
        jfxrt.jar...

4. Confirm the new version

java -version
java version "1.7.0_79"
Java(TM) SE Runtime Environment (build 1.7.0_79-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode)
十秒萌定你 2024-12-03 19:40:34

通过升级到 JDK 8 解决了该问题。

Solved the problem by upgrading to JDK 8.

烟火散人牵绊 2024-12-03 19:40:34

我在 JDK 1.6.45 上使用 Coldfusion 8,并且遇到了 问题;只给我红色十字而不是图像,并且 cfhttp 无法使用 ssl 连接到本地网络服务器。

我用 Coldfusion 8 重现的测试脚本

<CFHTTP URL="https://www.onlineumfragen.com" METHOD="get" ></CFHTTP>
<CFDUMP VAR="#CFHTTP#">

给了我一个非常普遍的错误“I/O 异常:对等点未经过身份验证”。
然后,我尝试将服务器的证书(包括根证书和中间证书)添加到 java 密钥库以及 Coldfusion 密钥库,但没有任何帮助。
然后我调试了问题

java SSLPoke www.onlineumfragen.com 443

并得到了

javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair

然后

Caused by: java.security.InvalidAlgorithmParameterException: Prime size must be
multiple of 64, and can only range from 512 to 1024 (inclusive)
    at com.sun.crypto.provider.DHKeyPairGenerator.initialize(DashoA13*..)
    at java.security.KeyPairGenerator$Delegate.initialize(KeyPairGenerator.java:627)
    at com.sun.net.ssl.internal.ssl.DHCrypt.<init>(DHCrypt.java:107)
    ... 10 more

我想到网络服务器(在我的例子中是apache)具有非常现代的ssl密码并且非常严格(qualys得分a +)并且使用超过1024位的强大的Diffie-hellman组。显然,ColdFusion 和 Java JDK 1.6.45 无法管理这一点。
下一步是考虑安装一个替代的 Java 安全提供程序,我决定使用 bouncy castle。
另请参见 http://www.itcsolutions.eu/2011/08/22/how-to-use-bouncy-castle-cryptographic-api-in-netbeans-or-eclipse-for-java-jse-projects/< /a>

下载

bcprov-ext-jdk15on-156.jar

然后我从 http://www.bouncycastle.org/latest_releases.html 并将其安装在
C:\jdk6_45\jre\lib\ext 或者你的 jdk 所在的位置,在 Coldfusion 8 的原始安装中,它将位于 C:\JRun4\jre\lib\ext 下,但我使用位于外部的较新的 jdk (1.6.45) Coldfusion 目录。将 bcprov-ext-jdk15on-156.jar 放在 \ext 目录中非常重要(这花了我大约两个小时和一些头发;-)
然后我编辑了文件 C:\jdk6_45\jre\lib\security\java.security (使用写字板而不是 editor.exe!)并为新提供程序添加一行。之后列表看起来像

#
# List of providers and their preference orders (see above):
#
security.provider.1=org.bouncycastle.jce.provider.BouncyCastleProvider
security.provider.2=sun.security.provider.Sun
security.provider.3=sun.security.rsa.SunRsaSign
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.9=sun.security.smartcardio.SunPCSC
security.provider.10=sun.security.mscapi.SunMSCAPI

(请参阅位置 1 中的新列表),

然后完全重新启动 Coldfusion 服务。
然后你就可以

java SSLPoke www.onlineumfragen.com 443 (or of course your url!)

享受这种感觉了...
当然

多么美好的夜晚,多么美好的白天。希望这会对那里的人有帮助(部分或全部)。如果您有疑问,请发邮件给我 info ...(上面的域名)。

I use coldfusion 8 on JDK 1.6.45 and had problems with <cfdocument ...> giving me just red crosses instead of images, and also with cfhttp not able to connect to the local webserver with ssl.

my test script to reproduce with coldfusion 8 was

<CFHTTP URL="https://www.onlineumfragen.com" METHOD="get" ></CFHTTP>
<CFDUMP VAR="#CFHTTP#">

this gave me the quite generic error of " I/O Exception: peer not authenticated."
I then tried to add certificates of the server including root and intermediate certificates to the java keystore and also the coldfusion keystore, but nothing helped.
then I debugged the problem with

java SSLPoke www.onlineumfragen.com 443

and got

javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair

and

Caused by: java.security.InvalidAlgorithmParameterException: Prime size must be
multiple of 64, and can only range from 512 to 1024 (inclusive)
    at com.sun.crypto.provider.DHKeyPairGenerator.initialize(DashoA13*..)
    at java.security.KeyPairGenerator$Delegate.initialize(KeyPairGenerator.java:627)
    at com.sun.net.ssl.internal.ssl.DHCrypt.<init>(DHCrypt.java:107)
    ... 10 more

I then had the idea that the webserver (apache in my case) had very modern ciphers for ssl and is quite restrictive (qualys score a+) and uses strong Diffie-hellman groups with more than 1024 bits. Obviously, ColdFusion and Java JDK 1.6.45 can not manage this.
Next step in the odyssey was to think of installing an alternative security provider for java, and I decided for bouncy castle.
see also http://www.itcsolutions.eu/2011/08/22/how-to-use-bouncy-castle-cryptographic-api-in-netbeans-or-eclipse-for-java-jse-projects/

I then downloaded the

bcprov-ext-jdk15on-156.jar

from http://www.bouncycastle.org/latest_releases.html and installed it under
C:\jdk6_45\jre\lib\ext or where ever your jdk is, in original install of coldfusion 8 it would be under C:\JRun4\jre\lib\ext but I use a newer jdk (1.6.45) located outside the coldfusion directory. it is very important to put the bcprov-ext-jdk15on-156.jar in the \ext directory (this cost me about two hours and some hair ;-)
then I edited the file C:\jdk6_45\jre\lib\security\java.security (with wordpad not with editor.exe!) and put in one line for the new provider. afterwards the list looked like

#
# List of providers and their preference orders (see above):
#
security.provider.1=org.bouncycastle.jce.provider.BouncyCastleProvider
security.provider.2=sun.security.provider.Sun
security.provider.3=sun.security.rsa.SunRsaSign
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.9=sun.security.smartcardio.SunPCSC
security.provider.10=sun.security.mscapi.SunMSCAPI

(see the new one in position 1)

then restart coldfusion service completely.
you can then

java SSLPoke www.onlineumfragen.com 443 (or of course your url!)

and enjoy the feeling...
and of course
<cfhttp and <cfdocument worked like a charm and like before we "hardened" our ssl ciphers in apache!

what a night and what a day. Hopefully this will help (partially or fully) to someone out there. if you have questions, just mail me at info ... (domain above).

放赐 2024-12-03 19:40:34

我们返回了完全相同的异常错误,在上网冲浪几个小时后修复它很容易。

我们在oracle.com上下载了我们能找到的最高版本的jdk,安装它并将Jboss应用服务器指向安装的新jdk的目录。

重启Jboss,重新处理,问题解决!!!

We got the same exact exception error returned, to fix it was easy after hours surfing the internet.

We downloaded the highest version of jdk we could find on oracle.com, installed it and pointed Jboss application server to the directory of the installed new jdk.

Restarted Jboss, reprocessed, problemo fixed!!!

甜中书 2024-12-03 19:40:34

我在 Bamboo 5.7 + Gradle 项目 + Apache 中遇到此错误。 Gradle 尝试通过 SSL 从我们的一台服务器获取一些依赖项。

解决方案:

  1. 生成 DH 参数:

使用 OpenSSL:

openssl dhparam 1024

示例输出:

-----BEGIN DH PARAMETERS-----
MIGHfoGBALxpfMrDpImEuPlhopxYX4L2CFqQov+FomjKyHJrzj/EkTP0T3oAkjnS
oCGh6p07kwSLS8WCtYJn1GzItiZ05LoAzPs7T3ST2dWrEYFg/dldt+arifj6oWo+
vctDyDqIjlevUE+vyR9MF6B+Rfm4Zs8VGkxmsgXuz0gp/9lmftY7AgEC
-----END DH PARAMETERS-----
  1. 将输出附加到证书文件(对于 Apache - SSLCertificateFile 参数)

  2. 重新启动 apache

  3. 重新启动 Bamboo

  4. 尝试构建项目再次

I've got this error with Bamboo 5.7 + Gradle project + Apache. Gradle tried to get some dependencies from one of our servers via SSL.

Solution:

  1. Generate DH Param:

with OpenSSL:

openssl dhparam 1024

example output:

-----BEGIN DH PARAMETERS-----
MIGHfoGBALxpfMrDpImEuPlhopxYX4L2CFqQov+FomjKyHJrzj/EkTP0T3oAkjnS
oCGh6p07kwSLS8WCtYJn1GzItiZ05LoAzPs7T3ST2dWrEYFg/dldt+arifj6oWo+
vctDyDqIjlevUE+vyR9MF6B+Rfm4Zs8VGkxmsgXuz0gp/9lmftY7AgEC
-----END DH PARAMETERS-----
  1. Append output to certificate file (for Apache - SSLCertificateFile param)

  2. Restart apache

  3. Restart Bamboo

  4. Try to build project again

陈独秀 2024-12-03 19:40:34

我曾经在使用 IBM JDK 通过 java SVN 客户端访问 svn.apache.org 时遇到类似的错误。目前,svn.apache.org 使用客户端密码首选项。

在使用数据包捕获 / javax.net.debug=ALL 运行一次后,我能够将一个 DHE 密码列入黑名单,并且一切对我有用(ECDHE 是协商的)。

.../java/jre/lib/security/java.security:
    jdk.tls.disabledAlgorithms=SSL_DHE_RSA_WITH_AES_256_CBC_SHA

当改变客户端并不容易时,这是一个很好的快速修复方法。

I used to get a similar error accessing svn.apache.org with java SVN clients using an IBM JDK. Currently, svn.apache.org users the clients cipher preferences.

After running just once with a packet capture / javax.net.debug=ALL I was able to blacklist just a single DHE cipher and things work for me (ECDHE is negotiated instead).

.../java/jre/lib/security/java.security:
    jdk.tls.disabledAlgorithms=SSL_DHE_RSA_WITH_AES_256_CBC_SHA

A nice quick fix when it is not easy to change the client.

无需解释 2024-12-03 19:40:34

最近我遇到了同样的问题,将 jdk 版本从 1.6.0_45 升级到 jdk1.7.0_191 后解决了该问题。

Recently I have the same issue and after upgrading jdk version from 1.6.0_45 to jdk1.7.0_191 which resolved the issue.

北方的韩爷 2024-12-03 19:40:34

如果服务器支持不包含 DH 的密码,您可以强制客户端选择该密码并避免 DH 错误。例如:

String pickedCipher[] ={"TLS_RSA_WITH_AES_256_CBC_SHA"};
sslsocket.setEnabledCipherSuites(pickedCipher);

请记住,从长远来看,指定精确的密码很容易被破坏。

If the server supports a cipher that does not include DH, you can force the client to select that cipher and avoid the DH error. Such as:

String pickedCipher[] ={"TLS_RSA_WITH_AES_256_CBC_SHA"};
sslsocket.setEnabledCipherSuites(pickedCipher);

Keep in mind that specifying an exact cipher is prone to breakage in the long run.

悸初 2024-12-03 19:40:34

对我来说,以下命令行解决了该问题:

java -jar -Dhttps.protocols=TLSv1.2 -Ddeployment.security.TLSv1.2=true
-Djavax.net.debug=ssl:handshake XXXXX.jar

我使用的是 JDK 1.7.0_79

For me, the following command line fixed the issue:

java -jar -Dhttps.protocols=TLSv1.2 -Ddeployment.security.TLSv1.2=true
-Djavax.net.debug=ssl:handshake XXXXX.jar

I am using JDK 1.7.0_79

ぽ尐不点ル 2024-12-03 19:40:34

窗口->首选项-> Java->安装的 JRE -> 选择 jre 并编辑。在“默认 VM 参数”中输入

-Dcom.sun.net.ssl.enableECC=false

单击“完成”

Window -> Preferences -> Java -> Installed JREs ->select the jre and Edit. And in the Default VM Arguments enter

-Dcom.sun.net.ssl.enableECC=false

Click Finish

一杯敬自由 2024-12-03 19:40:33

问题在于素数大小。 Java 接受的最大可接受大小是 1024 位。这是一个已知问题(请参阅 JDK-6521495)。

我链接到的错误报告提到了解决方法 使用 BouncyCastle 的 JCE 实现。希望这对你有用。

更新

这被报告为错误JDK-7044060 最近已修复。

但请注意,限制仅提高到 2048 位。对于尺寸> 2048位,有JDK-8072452 - 删除DH密钥的最大素数大小 ;该修复似乎适用于 9。

The problem is the prime size. The maximum-acceptable size that Java accepts is 1024 bits. This is a known issue (see JDK-6521495).

The bug report that I linked to mentions a workaround using BouncyCastle's JCE implementation. Hopefully that should work for you.

UPDATE

This was reported as bug JDK-7044060 and fixed recently.

Note, however, that the limit was only raised to 2048 bit. For sizes > 2048 bit, there is JDK-8072452 - Remove the maximum prime size of DH Keys; the fix appears to be for 9.

坚持沉默 2024-12-03 19:40:33

“Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files”的答案对我不起作用,但 BouncyCastle 的 JCE 提供商建议却起作用。

以下是我在 Mac OSC 10.7.5 上使用 Java 1.6.0_65-b14-462 所采取的步骤

1) 下载这些 jar:

2) 将这些 jar 移动到 $JAVA_HOME/lib/ext

3) 编辑$JAVA_HOME/lib/security/java.security 如下:
security.provider.1=org.bouncycastle.jce.provider.BouncyCastleProvider

使用 JRE 重新启动应用程序并尝试一下

The "Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files" answer did not work for me but The BouncyCastle's JCE provider suggestion did.

Here are the steps I took using Java 1.6.0_65-b14-462 on Mac OSC 10.7.5

1) Download these jars:

2) move these jars to $JAVA_HOME/lib/ext

3) edit $JAVA_HOME/lib/security/java.security as follows:
security.provider.1=org.bouncycastle.jce.provider.BouncyCastleProvider

restart app using JRE and give it a try

苏别ゝ 2024-12-03 19:40:33

这是我的解决方案(java 1.6),也对为什么我必须这样做感兴趣:

我从 javax.security.debug=ssl 注意到,有时使用的密码套件是 TLS_DHE_...有时是 TLS_ECDHE_.. .. 如果我添加 BouncyCastle,就会发生后者。如果选择了 TLS_ECDHE_,大多数情况下它都可以工作,但并非总是如此,因此即使添加 BouncyCastle 提供程序也是不可靠的(每隔一段时间就会失败并出现相同的错误)。我猜想 Sun SSL 实现中的某个地方有时会选择DHE,有时会选择ECDHE

因此,此处发布的解决方案依赖于完全删除 TLS_DHE_ 密码。注意:该解决方案不需要 BouncyCastle。

因此,通过以下方式创建服务器认证文件:

echo |openssl s_client -connect example.org:443 2>&1 |sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'

保存此文件,因为稍后会引用它,这里是 SSL http get 的解决方案,不包括 TLS_DHE_ 密码套件。

package org.example.security;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URL;
import java.net.UnknownHostException;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

import org.apache.log4j.Logger;

public class SSLExcludeCipherConnectionHelper {

    private Logger logger = Logger.getLogger(SSLExcludeCipherConnectionHelper.class);

    private String[] exludedCipherSuites = {"_DHE_","_DH_"};

    private String trustCert = null;

    private TrustManagerFactory tmf;

    public void setExludedCipherSuites(String[] exludedCipherSuites) {
        this.exludedCipherSuites = exludedCipherSuites;
    }

    public SSLExcludeCipherConnectionHelper(String trustCert) {
        super();
        this.trustCert = trustCert;
        //Security.addProvider(new BouncyCastleProvider());
        try {
            this.initTrustManager();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void initTrustManager() throws Exception {
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream caInput = new BufferedInputStream(new FileInputStream(trustCert));
        Certificate ca = null;
        try {
            ca = cf.generateCertificate(caInput);
            logger.debug("ca=" + ((X509Certificate) ca).getSubjectDN());
        } finally {
            caInput.close();
        }

        // Create a KeyStore containing our trusted CAs
        KeyStore keyStore = KeyStore.getInstance("jks");
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        // Create a TrustManager that trusts the CAs in our KeyStore
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);
    }

    public String get(URL url) throws Exception {
        // Create an SSLContext that uses our TrustManager
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, tmf.getTrustManagers(), null);
        SSLParameters params = context.getSupportedSSLParameters();
        List<String> enabledCiphers = new ArrayList<String>();
        for (String cipher : params.getCipherSuites()) {
            boolean exclude = false;
            if (exludedCipherSuites != null) {
                for (int i=0; i<exludedCipherSuites.length && !exclude; i++) {
                    exclude = cipher.indexOf(exludedCipherSuites[i]) >= 0;
                }
            }
            if (!exclude) {
                enabledCiphers.add(cipher);
            }
        }
        String[] cArray = new String[enabledCiphers.size()];
        enabledCiphers.toArray(cArray);

        // Tell the URLConnection to use a SocketFactory from our SSLContext
        HttpsURLConnection urlConnection =
            (HttpsURLConnection)url.openConnection();
        SSLSocketFactory sf = context.getSocketFactory();
        sf = new DOSSLSocketFactory(sf, cArray);
        urlConnection.setSSLSocketFactory(sf);
        BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
        String inputLine;
        StringBuffer buffer = new StringBuffer();
        while ((inputLine = in.readLine()) != null) 
            buffer.append(inputLine);
        in.close();

        return buffer.toString();
    }

    private class DOSSLSocketFactory extends javax.net.ssl.SSLSocketFactory {

        private SSLSocketFactory sf = null;
        private String[] enabledCiphers = null;

        private DOSSLSocketFactory(SSLSocketFactory sf, String[] enabledCiphers) {
            super();
            this.sf = sf;
            this.enabledCiphers = enabledCiphers;
        }

        private Socket getSocketWithEnabledCiphers(Socket socket) {
            if (enabledCiphers != null && socket != null && socket instanceof SSLSocket)
                ((SSLSocket)socket).setEnabledCipherSuites(enabledCiphers);

            return socket;
        }

        @Override
        public Socket createSocket(Socket s, String host, int port,
                boolean autoClose) throws IOException {
            return getSocketWithEnabledCiphers(sf.createSocket(s, host, port, autoClose));
        }

        @Override
        public String[] getDefaultCipherSuites() {
            return sf.getDefaultCipherSuites();
        }

        @Override
        public String[] getSupportedCipherSuites() {
            if (enabledCiphers == null)
                return sf.getSupportedCipherSuites();
            else
                return enabledCiphers;
        }

        @Override
        public Socket createSocket(String host, int port) throws IOException,
                UnknownHostException {
            return getSocketWithEnabledCiphers(sf.createSocket(host, port));
        }

        @Override
        public Socket createSocket(InetAddress address, int port)
                throws IOException {
            return getSocketWithEnabledCiphers(sf.createSocket(address, port));
        }

        @Override
        public Socket createSocket(String host, int port, InetAddress localAddress,
                int localPort) throws IOException, UnknownHostException {
            return getSocketWithEnabledCiphers(sf.createSocket(host, port, localAddress, localPort));
        }

        @Override
        public Socket createSocket(InetAddress address, int port,
                InetAddress localaddress, int localport) throws IOException {
            return getSocketWithEnabledCiphers(sf.createSocket(address, port, localaddress, localport));
        }

    }
}

最后是它的使用方法(如果是从 openssl 保存的证书的路径,则为 certFilePath):

try {
            URL url = new URL("https://www.example.org?q=somedata");            
            SSLExcludeCipherConnectionHelper sslExclHelper = new SSLExcludeCipherConnectionHelper(certFilePath);
            logger.debug(
                    sslExclHelper.get(url)
            );
        } catch (Exception ex) {
            ex.printStackTrace();
        }

Here is my solution (java 1.6), also would be interested why I had to do this:

I noticed from the javax.security.debug=ssl, that sometimes the used cipher suite is TLS_DHE_... and sometime it is TLS_ECDHE_.... The later would happen if I added BouncyCastle. If TLS_ECDHE_ was selected, MOST OF the time it worked, but not ALWAYS, so adding even BouncyCastle provider was unreliable (failed with same error, every other time or so). I guess somewhere in the Sun SSL implementation sometimes it choose DHE, sometimes it choose ECDHE.

So the solution posted here relies on removing TLS_DHE_ ciphers completely. NOTE: BouncyCastle is NOT required for the solution.

So create the server certification file by:

echo |openssl s_client -connect example.org:443 2>&1 |sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'

Save this as it will be referenced later, than here is the solution for an SSL http get, excluding the TLS_DHE_ cipher suites.

package org.example.security;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URL;
import java.net.UnknownHostException;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

import org.apache.log4j.Logger;

public class SSLExcludeCipherConnectionHelper {

    private Logger logger = Logger.getLogger(SSLExcludeCipherConnectionHelper.class);

    private String[] exludedCipherSuites = {"_DHE_","_DH_"};

    private String trustCert = null;

    private TrustManagerFactory tmf;

    public void setExludedCipherSuites(String[] exludedCipherSuites) {
        this.exludedCipherSuites = exludedCipherSuites;
    }

    public SSLExcludeCipherConnectionHelper(String trustCert) {
        super();
        this.trustCert = trustCert;
        //Security.addProvider(new BouncyCastleProvider());
        try {
            this.initTrustManager();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void initTrustManager() throws Exception {
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream caInput = new BufferedInputStream(new FileInputStream(trustCert));
        Certificate ca = null;
        try {
            ca = cf.generateCertificate(caInput);
            logger.debug("ca=" + ((X509Certificate) ca).getSubjectDN());
        } finally {
            caInput.close();
        }

        // Create a KeyStore containing our trusted CAs
        KeyStore keyStore = KeyStore.getInstance("jks");
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        // Create a TrustManager that trusts the CAs in our KeyStore
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);
    }

    public String get(URL url) throws Exception {
        // Create an SSLContext that uses our TrustManager
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, tmf.getTrustManagers(), null);
        SSLParameters params = context.getSupportedSSLParameters();
        List<String> enabledCiphers = new ArrayList<String>();
        for (String cipher : params.getCipherSuites()) {
            boolean exclude = false;
            if (exludedCipherSuites != null) {
                for (int i=0; i<exludedCipherSuites.length && !exclude; i++) {
                    exclude = cipher.indexOf(exludedCipherSuites[i]) >= 0;
                }
            }
            if (!exclude) {
                enabledCiphers.add(cipher);
            }
        }
        String[] cArray = new String[enabledCiphers.size()];
        enabledCiphers.toArray(cArray);

        // Tell the URLConnection to use a SocketFactory from our SSLContext
        HttpsURLConnection urlConnection =
            (HttpsURLConnection)url.openConnection();
        SSLSocketFactory sf = context.getSocketFactory();
        sf = new DOSSLSocketFactory(sf, cArray);
        urlConnection.setSSLSocketFactory(sf);
        BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
        String inputLine;
        StringBuffer buffer = new StringBuffer();
        while ((inputLine = in.readLine()) != null) 
            buffer.append(inputLine);
        in.close();

        return buffer.toString();
    }

    private class DOSSLSocketFactory extends javax.net.ssl.SSLSocketFactory {

        private SSLSocketFactory sf = null;
        private String[] enabledCiphers = null;

        private DOSSLSocketFactory(SSLSocketFactory sf, String[] enabledCiphers) {
            super();
            this.sf = sf;
            this.enabledCiphers = enabledCiphers;
        }

        private Socket getSocketWithEnabledCiphers(Socket socket) {
            if (enabledCiphers != null && socket != null && socket instanceof SSLSocket)
                ((SSLSocket)socket).setEnabledCipherSuites(enabledCiphers);

            return socket;
        }

        @Override
        public Socket createSocket(Socket s, String host, int port,
                boolean autoClose) throws IOException {
            return getSocketWithEnabledCiphers(sf.createSocket(s, host, port, autoClose));
        }

        @Override
        public String[] getDefaultCipherSuites() {
            return sf.getDefaultCipherSuites();
        }

        @Override
        public String[] getSupportedCipherSuites() {
            if (enabledCiphers == null)
                return sf.getSupportedCipherSuites();
            else
                return enabledCiphers;
        }

        @Override
        public Socket createSocket(String host, int port) throws IOException,
                UnknownHostException {
            return getSocketWithEnabledCiphers(sf.createSocket(host, port));
        }

        @Override
        public Socket createSocket(InetAddress address, int port)
                throws IOException {
            return getSocketWithEnabledCiphers(sf.createSocket(address, port));
        }

        @Override
        public Socket createSocket(String host, int port, InetAddress localAddress,
                int localPort) throws IOException, UnknownHostException {
            return getSocketWithEnabledCiphers(sf.createSocket(host, port, localAddress, localPort));
        }

        @Override
        public Socket createSocket(InetAddress address, int port,
                InetAddress localaddress, int localport) throws IOException {
            return getSocketWithEnabledCiphers(sf.createSocket(address, port, localaddress, localport));
        }

    }
}

Finally here is how it is used (certFilePath if the path of the certificate saved from openssl):

try {
            URL url = new URL("https://www.example.org?q=somedata");            
            SSLExcludeCipherConnectionHelper sslExclHelper = new SSLExcludeCipherConnectionHelper(certFilePath);
            logger.debug(
                    sslExclHelper.get(url)
            );
        } catch (Exception ex) {
            ex.printStackTrace();
        }
独行侠 2024-12-03 19:40:33

上面的答案是正确的,但就解决方法而言,当我将 BouncyCastle 设置为首选提供程序时,我遇到了问题:

java.lang.ArrayIndexOutOfBoundsException: 64
    at com.sun.crypto.provider.TlsPrfGenerator.expand(DashoA13*..)

这也在我发现的一个论坛主题中进行了讨论,但没有提到解决方案。
http://www.javakb.com/Uwe/Forum .aspx/java-programmer/47512/TLS-problems

我找到了一个适合我的情况的替代解决方案,尽管我对此一点也不满意。解决办法就是设置它,让Diffie-Hellman算法根本不可用。然后,假设服务器支持替代算法,它将在正常协商期间进行选择。显然,这样做的缺点是,如果有人设法找到一个仅支持 1024 位或更少的 Diffie-Hellman 的服务器,那么这实际上意味着它无法在以前工作的地方工作。

下面是给定 SSLSocket 的代码(在连接之前):

List<String> limited = new LinkedList<String>();
for(String suite : ((SSLSocket)s).getEnabledCipherSuites())
{
    if(!suite.contains("_DHE_"))
    {
        limited.add(suite);
    }
}
((SSLSocket)s).setEnabledCipherSuites(limited.toArray(
    new String[limited.size()]));

令人讨厌的。

The answer above is correct, but in terms of the workaround, I had problems with the BouncyCastle implementation when I set it as preferred provider:

java.lang.ArrayIndexOutOfBoundsException: 64
    at com.sun.crypto.provider.TlsPrfGenerator.expand(DashoA13*..)

This is also discussed in one forum thread I found, which doesn't mention a solution.
http://www.javakb.com/Uwe/Forum.aspx/java-programmer/47512/TLS-problems

I found an alternative solution which works for my case, although I'm not at all happy with it. The solution is to set it so that the Diffie-Hellman algorithm is not available at all. Then, supposing the server supports an alternative algorithm, it will be selecting during normal negotiation. Obviously the downside of this is that if somebody somehow manages to find a server that only supports Diffie-Hellman at 1024 bits or less then this actually means it will not work where it used to work before.

Here is code which works given an SSLSocket (before you connect it):

List<String> limited = new LinkedList<String>();
for(String suite : ((SSLSocket)s).getEnabledCipherSuites())
{
    if(!suite.contains("_DHE_"))
    {
        limited.add(suite);
    }
}
((SSLSocket)s).setEnabledCipherSuites(limited.toArray(
    new String[limited.size()]));

Nasty.

过期情话 2024-12-03 19:40:33

您可以在 jdk 中完全禁用 DHE,编辑 jre/lib/security/java.security 并确保禁用 DHE,例如。例如

jdk.tls.disabledAlgorithms=SSLv3,DHE

You can disable DHE completely in your jdk, edit jre/lib/security/java.security and make sure DHE is disabled, eg. like

jdk.tls.disabledAlgorithms=SSLv3, DHE.

初见 2024-12-03 19:40:33

您可以动态安装提供程序:

1) 下载这些 jar:

  • bcprov-jdk15on-152.jar
  • bcprov-ext-jdk15on-152.jar

2) 将 jar 复制到 WEB-INF/lib(或您的类路径)

3)动态添加提供程序:

import org.bouncycastle.jce.provider.BouncyCastleProvider;

...

Security.addProvider(new BouncyCastleProvider());

You can installing the provider dynamically:

1) Download these jars:

  • bcprov-jdk15on-152.jar
  • bcprov-ext-jdk15on-152.jar

2) Copy jars to WEB-INF/lib (or your classpath)

3) Add provider dynamically:

import org.bouncycastle.jce.provider.BouncyCastleProvider;

...

Security.addProvider(new BouncyCastleProvider());

菊凝晚露 2024-12-03 19:40:33

这是一篇相当老的文章,但是如果您使用 Apache HTTPD,则可以限制 DH 大小。
请参阅http://httpd.apache.org/docs/current/ssl/ssl_faq.html#javadh

This is a quite old post, but if you use Apache HTTPD, you can limit the DH size.
See http://httpd.apache.org/docs/current/ssl/ssl_faq.html#javadh

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文