Java SSLContext.getInstance("TLS")漏洞修复及多TLS版本兼容实现问询
Java SSLContext TLS版本配置问题解答
核心认知纠正
SSLContext.getInstance()的入参不是仅支持的版本,也不是最高支持版本,它只是要求返回的SSLContext实例至少支持你传入的协议版本,实际支持的协议范围由JDK的全局安全配置(java.security文件中的jdk.tls.disabledAlgorithms项)决定。
你测试时传入"TLSv1.3"能自动降级到TLSv1.2属于正常行为,这不叫不安全的算法降级——只有降级到TLSv1.1及以下的不安全版本才属于漏洞,TLSv1.2目前仍是行业认可的安全版本。
为什么用"TLSv1.2"作为入参无法启用TLSv1.3
部分JDK版本中,当你传入"TLSv1.2"初始化SSLContext时,上下文会被限制最高仅支持到TLSv1.2,后续调用setEnabledProtocols添加TLSv1.3也不会生效,因为上下文本身已经不支持更高版本。
符合要求的实现方案
你的需求是适配三种服务端场景(仅支持TLSv1.2、仅支持TLSv1.3、同时支持两个版本),同时要避开静态扫描的漏洞告警,可以按以下方式实现:
适用JDK8u261+、JDK11+等原生支持TLSv1.3的版本
直接用以下代码即可:
// 入参用TLSv1.3绕过静态扫描告警 SSLContext sslContext = SSLContext.getInstance("TLSv1.3"); sslContext.init(null, null, new SecureRandom()); SSLSocket sslSocket = (SSLSocket) sslContext.getSocketFactory().createSocket("你的服务端域名", 443); // 手动指定仅启用安全的TLS版本,优先级TLSv1.3在前 sslSocket.setEnabledProtocols(new String[]{"TLSv1.3", "TLSv1.2"});
这个实现可以自动适配三种场景:
- 服务端仅支持TLSv1.2:协商时自动选TLSv1.2,连接正常
- 服务端仅支持TLSv1.3:协商时自动选TLSv1.3,连接正常
- 服务端同时支持两个版本:优先选安全性更高的TLSv1.3
需兼容不支持TLSv1.3的老旧JDK版本
可以动态判断当前JDK支持的协议版本,过滤出安全版本后再设置:
SSLContext sslContext = SSLContext.getInstance("TLSv1.3"); sslContext.init(null, null, new SecureRandom()); List<String> supportedProtocols = Arrays.asList(sslContext.getSupportedSSLParameters().getProtocols()); List<String> safeProtocols = new ArrayList<>(); // 优先添加高版本安全协议 if (supportedProtocols.contains("TLSv1.3")) { safeProtocols.add("TLSv1.3"); } safeProtocols.add("TLSv1.2"); SSLSocket sslSocket = (SSLSocket) sslContext.getSocketFactory().createSocket("你的服务端域名", 443); sslSocket.setEnabledProtocols(safeProtocols.toArray(new String[0]));
补充说明
如果你用的是SSLEngine(比如Netty等异步框架场景),设置逻辑和SSLSocket完全一致,调用SSLEngine.setEnabledProtocols()方法设置即可。
内容的提问来源于stack exchange,提问作者Andreas Mueller
相关产品推荐
相关产品推荐

