获取无法生成 DH 密钥对异常

Getting Could not generate DH keypair Exception

当 vCenter(5.5) 尝试从 https 服务器下载 zip 文件时出现此异常。 VCenter 服务器有 JRE 1.6.0.31。我知道 Java 1.6 和 1.7 中与同一问题相关的错误。此异常是由 java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive).

引起的

我可以从 https 服务器更改 SSL 证书。我试图通过使用 OpenSSL (openssl req -new -x509 -newkey rsa:1024 -days 365 -out server.crt -extensions usr_cert 生成新证书来解决这个问题 ) 和其他选项。我查看了 sun.security.ssl.ClientHandshaker 代码,有一个 switch case 执行 以下代码行并生成异常。

case K_DHE_DSS:
case K_DHE_RSA:
    this.serverKeyExchange(new DH_ServerKeyExchange(input, serverKey,
    clnt_random.random_bytes, svr_random.random_bytes,messageLen));

有什么方法可以生成 SSL 证书来避免此代码执行(可能是没有 DH 密钥对的 SSL 证书)?

提前致谢!

密钥交换是 DHE_RSA 这意味着 Diffie Hellman Ephemeral 通过 RSA 验证。 DHE 密钥,甚至 DHE 参数,不在证书中,这是长期的(FSVO 长)而不是短暂的。证书中的密钥是 RSA,Java 处理安全大小的 RSA 没有问题,今天超过 1024,通常是 2048。

  1. 直接修复是使用旧的Java兼容弱DH(E)参数。可能有十几个或更多 SSL/TLS 服务器程序使用 OpenSSL,或者使用 PEM 格式文件作为证书 and (RSA) 私钥。 (很多 软件使用或可以处理 cert 的 PEM,但大多数 OpenSSL 为私钥这样做。)许多这些服务器程序允许配置 DH (E) 参数,但我所看到的所有参数都是不同的,而且您无法识别您的参数。

  2. 一种解决方法是避免使用 DHE_anything 并使用 plain-RSA 密钥交换。包括 OpenSSL 在内的所有 SSL/TLS 实现都实现了这一点。然而,大多数应用程序 and/or 中间件不再喜欢它,有些甚至不允许它,因为它不提供 Forward Secrecy。您如何控制密码套件以及密钥交换,同样取决于未识别的服务器程序。

  3. 更好的解决方法是启用 ECDHE(特别是 ECDHE_RSA,因为您的 cert/key 是 RSA) .

    3A。 Java6 JSSE 实现了 ECDHE 协议,但仅当您的 JRE 中有用于 ECC 原语的 JCE "provider" 和已交付的 Oracle/Sun JRE6(以及 TTBOMK 和 OpenJDK 之一)时才启用它们没有 ECC 提供商。 将 ECC 提供程序 添加到 JRE6

    • http://www.bouncycastle.org/latest_releases.html 下载 bcprov-jdk15on-$version.jar 并将其放入您的 JRE/lib/ext

    • 编辑 JRE/lib/security/java.security 以在提供商列表中添加类似 security.provider.N=org.bouncycastle.jce.provider.BouncyCastleProvider 的行,其中 N 是下一个可用号码。

    JRE7 确实包含 ECC 提供程序,并且开箱即用地支持 ECDHE,如果这是一个选项。

    3B。如果您的服务器使用 OpenSSL 1.0.0 或更高版本(某些较旧的 RedHat 版本除外),它会实现 ECDHE,但它可以 只有在 (1) 启用密码套件时才能使用,这是真的默认情况下,但可以通过服务器程序或其配置禁用, (2) 服务器程序设置 tmp_ecdh 参数(或在 1.0.2 中启用自动设置)。这两者都取决于身份不明的服务器程序,如果服务器程序不使用 OpenSSL,答案可能会大不相同。

如果您确定您的服务器程序及其配置的SSL/TLS相关部分,我(或可能是其他人)可以更具体。

编辑 服务器是 nginx:

(1) nginx 应该可以使用 DHE params Java(6,7) 可以处理,参见 http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_dhparam 并使用

创建文件
 openssl dhparam 1024 >mydhfile

(或者,如果您确实需要,较小的 DSA-1 大小 = 512 到 1024 和 64 的倍数,但您不需要,我也不建议小于 1024)。

(2) 或者,要禁用 DHE,不要 添加它,但 至少添加一些 kRSA(或仅添加 RSA ) 在 ssl_ciphers 字符串中。至少将评论中的字符串更改为

 EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA256:EECDH:kRSA:!RC4:!aNU‌​LL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS

或者因为未修改的 JRE6 不会提供 ECDHE(或 TLSv1.2)并且我们没有添加任何需要删除的 PSK 或 SRP 或 DSS 或 aNULL,并且您不信任 3DES(为什么?)和 RC4并且 Java 没有实现 SEED 或 Camellia,您可以更简单地使用

 AES128-SHA:AES256-SHA 

(这些实际上是 TLS_RSA_WITH_AES*_CBC_SHA 但对于歇斯底里的葡萄干,OpenSSL 名称省略了 RSA 和 CBC。)

Tomcat 默认使用 Java (JSSE) 来处理 HTTPS 连接,但是根据 packaging/install 通常也可以使用 APR称为 "Tomcat native" 或 "native" 实际上是 OpenSSL。如果 Tomcat/JSSE 在 JRE6 或 7 上是 运行,它使用 JRE6,7 客户端可以处理的 DHE 大小 768;如果 运行 在 JRE8 上,它 默认 大小为 1024,JRE6,7 客户端可以处理。我不知道 Tomcat/APR 使用什么(并且无法轻松测试)但它很可能是 1024 或更少。如果你想找到 Tomcat/APR 运行ning 和 openssl 1.0.2 可用,请使用 openssl s_client -connect host:port -tls1 -cipher EDH+AES;当它连接时输入Q,return;并查看 "Server Temp Key".

的大约 20 行