不支持的曲线:Java 应用上的 1.2.840.10045.3.1.7
Unsupported curve: 1.2.840.10045.3.1.7 on Java app
我有一个 Java 8 应用程序在连接 ldaps 或 https 服务器时引发以下异常:
Caused by: javax.net.ssl.SSLHandshakeException:
Unsupported curve: 1.2.840.10045.3.1.7
我的客户端环境是:
Alpine Linux 3.5 on a Docker container
OpenJDK 1.8.0_111
Wildfly 10.1.0.Final
如果我从以下位置连接,我可以解决这个问题:
- 使用 AES128-SHA 密码 (TLSv1) 的 Alpine Linux 盒子
- 一个装有 CentOS 7 而不是 Alpine Linux 3.5(所有密码都有效)的容器
但是如果我从以下位置连接总是会失败:
- 使用 ECDHE-RSA-AES256-GCM-SHA384 密码 (TLSv1.2) 的 Alpine Linux 盒子
有什么建议可以解决我的 Alpine Linux 安装上的这个问题吗?
TL,DR:来自 Alpine 的 OpenJDK 8 包不支持使用椭圆曲线的密码,例如 ECDHE
。在 Java 选项上使用 -Dcom.sun.net.ssl.enableECC=false
以请求 OpenJDK 不要使用此类密码。
这个漂亮的 Atlassian paper 描述了如何使用以下代码从 JVM 列出所有默认和可用的密码:
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import javax.net.ssl.SSLServerSocketFactory;
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());
}
}
}
运行 来自 Alpine 3.5 的 OpenJDK 8 上的这段代码没有列出任何 ECDHE
密码,另一方面,这段相同的代码列出了安装在 CentOS 7 机器上的 OpenJDK 8 中的几个这样的密码.
出于某种原因,使用椭圆曲线的密码作为 Wildfly 应用程序上的可用密码从客户端发送到服务器。在 Wildfly 之外 - 例如 java SomeClass
或 java -jar some.jar
这些密码不会发送并且通信有效。在 Java 选项上添加 -Djavax.net.debug=all
可以观察到这种行为。
Alpine Linux 3.5 的 openjdk8-jre-base 包 8.111.14-r1 不包含 libsunec.so,SunEC 提供程序查找的库,但 Alpine Linux 3.3 (8.92.14-r0) 和 3.4 (8.111.14-r0) 可以(请参阅 this package search). I've opened Alpine issue #6809。
解决此问题的最简单方法可能是回滚到 Alpine 3.4。或者,您可以在 3.5 中安装 3.4 版本的 openjdk8-jre-base,但是如果您走这条路,您可能 运行 会遇到一些依赖问题。
如果您想使用 Alpine Linux 3.5 包,您可以让您的 java 应用程序使用备用 JCE 提供程序,例如 BouncyCastle。
如果您不需要 EC 加密,您可以禁用它,但请注意,这样做会使您的应用程序无法使用多个常见的 PFS 密码套件。
我有一个 Java 8 应用程序在连接 ldaps 或 https 服务器时引发以下异常:
Caused by: javax.net.ssl.SSLHandshakeException:
Unsupported curve: 1.2.840.10045.3.1.7
我的客户端环境是:
Alpine Linux 3.5 on a Docker container
OpenJDK 1.8.0_111
Wildfly 10.1.0.Final
如果我从以下位置连接,我可以解决这个问题:
- 使用 AES128-SHA 密码 (TLSv1) 的 Alpine Linux 盒子
- 一个装有 CentOS 7 而不是 Alpine Linux 3.5(所有密码都有效)的容器
但是如果我从以下位置连接总是会失败:
- 使用 ECDHE-RSA-AES256-GCM-SHA384 密码 (TLSv1.2) 的 Alpine Linux 盒子
有什么建议可以解决我的 Alpine Linux 安装上的这个问题吗?
TL,DR:来自 Alpine 的 OpenJDK 8 包不支持使用椭圆曲线的密码,例如 ECDHE
。在 Java 选项上使用 -Dcom.sun.net.ssl.enableECC=false
以请求 OpenJDK 不要使用此类密码。
这个漂亮的 Atlassian paper 描述了如何使用以下代码从 JVM 列出所有默认和可用的密码:
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import javax.net.ssl.SSLServerSocketFactory;
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());
}
}
}
运行 来自 Alpine 3.5 的 OpenJDK 8 上的这段代码没有列出任何 ECDHE
密码,另一方面,这段相同的代码列出了安装在 CentOS 7 机器上的 OpenJDK 8 中的几个这样的密码.
出于某种原因,使用椭圆曲线的密码作为 Wildfly 应用程序上的可用密码从客户端发送到服务器。在 Wildfly 之外 - 例如 java SomeClass
或 java -jar some.jar
这些密码不会发送并且通信有效。在 Java 选项上添加 -Djavax.net.debug=all
可以观察到这种行为。
Alpine Linux 3.5 的 openjdk8-jre-base 包 8.111.14-r1 不包含 libsunec.so,SunEC 提供程序查找的库,但 Alpine Linux 3.3 (8.92.14-r0) 和 3.4 (8.111.14-r0) 可以(请参阅 this package search). I've opened Alpine issue #6809。
解决此问题的最简单方法可能是回滚到 Alpine 3.4。或者,您可以在 3.5 中安装 3.4 版本的 openjdk8-jre-base,但是如果您走这条路,您可能 运行 会遇到一些依赖问题。
如果您想使用 Alpine Linux 3.5 包,您可以让您的 java 应用程序使用备用 JCE 提供程序,例如 BouncyCastle。
如果您不需要 EC 加密,您可以禁用它,但请注意,这样做会使您的应用程序无法使用多个常见的 PFS 密码套件。