GraalVM Java 8下SSLEngine仅支持指定加密套件问题排查
问题描述
我编写了如下Java程序:
import java.util.Arrays; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; public class Example { public static void main(String[] args) throws Exception { SSLContext context = SSLContext.getInstance("TLS"); context.init(null, null, null); SSLEngine engine = context.createSSLEngine(); System.out.println(Arrays.toString(engine.getSupportedCipherSuites())); } }
运行环境:
openjdk version "1.8.0_302" OpenJDK Runtime Environment (build 1.8.0_302-b07) OpenJDK 64-Bit Server VM GraalVM LIBGRAAL 20.3.3 (build 25.302-b07-jvmci-20.3-b20, mixed mode)
程序输出:
[TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
当前加密提供者:
SunJSSE version 1.8
查看jre/lib/security/java.security配置,并未禁用所有标准加密套件:
jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \ DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \ include jdk.disabled.namedCurves [...] jdk.tls.legacyAlgorithms= \ K_NULL, C_NULL, M_NULL, \ DH_anon, ECDH_anon, \ RC4_128, RC4_40, DES_CBC, DES40_CBC, \ 3DES_EDE_CBC
请问所有TLS 1.2和TLS 1.3加密套件去哪了?还有哪些因素会影响加密套件的选择?
问题分析与解答
为什么仅显示TLS_EMPTY_RENEGOTIATION_INFO_SCSV?
核心原因是你调用context.init(null, null, null)时,传入了空的密钥管理器(KeyManager)和信任管理器(TrustManager)。这种情况下,JSSE会创建一个无密钥材料的空SSL上下文,无法支持任何需要身份验证(甚至非匿名类)的标准加密套件。
TLS_EMPTY_RENEGOTIATION_INFO_SCSV是一个特殊的信号套件,不用于实际加密通信,仅用于TLS重新协商的信息交互,不需要密钥材料,因此会被保留。
要解决这个问题,你需要初始化包含有效密钥/信任材料的SSL上下文:
- 若仅需查看支持的套件列表,可使用默认的密钥和信任管理器:
// 使用默认KeyManager和TrustManager初始化 context.init(null, SSLContext.getDefault().getTrustManagers(), null);
或者直接获取默认SSLContext:
SSLContext context = SSLContext.getDefault();
这样就能看到完整的支持加密套件列表。
2. 若需自定义密钥/信任逻辑,需创建对应的KeyManager和TrustManager实例传入init方法。
另外需要注意:OpenJDK 8本身不支持TLS 1.3,该协议从OpenJDK 11开始正式纳入支持,因此即便配置正确,你也无法看到TLS 1.3相关的套件。
影响加密套件选择的因素
除了代码中的SSLContext初始化方式,以下因素也会直接影响可用的加密套件:
- JDK版本:不同版本支持的套件范围差异明显,比如TLS 1.3仅在JDK11+支持,旧版本会逐步淘汰弱加密套件。
java.security配置:jdk.tls.disabledAlgorithms:直接禁用指定算法、套件或密钥长度限制,匹配项会被排除出可用列表。jdk.tls.legacyAlgorithms:标记为遗留的算法,默认不启用,需显式配置才能使用。
- 加密提供者:不同安全提供者(如SunJSSE、BouncyCastle)支持的套件范围不同,切换提供者会改变可用套件集合。
- SSL/TLS协议版本:初始化SSLContext时指定的协议版本(如
TLSv1.2)会过滤掉对应版本不兼容的套件。 - 密钥/信任材料有效性:若SSLContext没有有效密钥或信任材料,绝大多数需要身份验证的标准套件会不可用。
- 显式套件配置:通过
SSLEngine.setEnabledCipherSuites(...)或SSLSocket.setEnabledCipherSuites(...)可手动指定启用的套件,覆盖默认列表。
内容的提问来源于stack exchange,提问作者Savior
相关产品推荐
相关产品推荐

