如何向 Java 应用服务器添加额外的密码套件?

如何向 Java 应用服务器添加额外的密码套件?

我在从 Java 应用程序调用第三方 API 时遇到了一些麻烦。外部 API 至少需要以下密码之一:

TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256

我按照这里的说明进行操作:https://confluence.atlassian.com/stashkb/list-ciphers-used-by-jvm-679609085.html尝试升级我的应用服务器上可用的密码。但升级后,我仍然没有看到任何兼容的密码列出。

我怀疑问题在于我的服务器正在运行 jdk 1.7。这是一个遗留应用程序,因此很遗憾我无法升级到较新的 jdk。有没有办法将这些密码添加到我现有的 java 安装中?

更新: 我弄清楚了如何添加其他密码,但似乎没有帮助。在我的套接字工厂中,我添加了一些代码,如下所示:

private Socket acceptOnlyTLS12(Socket socket) {
        if (!(socket instanceof SSLSocket))
            return socket;
        SSLSocket sslSocket = (SSLSocket) socket;
        sslSocket.setEnabledProtocols(new String[] { "TLSv1.2" });
        List<String> ciphers = new ArrayList<String>(Arrays.asList(sslSocket.getEnabledCipherSuites()));
        ciphers.add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256");
        sslSocket.setEnabledCipherSuites(ciphers.toArray(new String[] {}));
        return sslSocket;
    }

我是否还遗漏了其他步骤?是否有某种方法可以获取有关 SSL 握手失败原因的其他信息?

答案1

(1)该网页的日期为 2014 年;2017 年之后的 Oracle Java 版本不再使用无限制策略,而在此之前(例如 7u80),它仅适用于对称加密超过 128 位这只会影响 AES256 套件,而不会影响 AES128 套件。(绝不适用于 OpenJDK,尽管低于 8 的 OpenJDK 主要仅在主要的 Linux 发行版(如 RedHat 和 Debian)上可用,这些发行版可以分配人员进行构建和打包;您没有说您正在使用哪一个。)

(2)Java(1.)7支持您展示的 CBC 密码套件(不是 GCM 密码套件,对于 7u171 以下的 Oracle 版本,AES256 密码套件确实需要无限制策略),但是仅当 TLS1.2被使用(这些密码套件在较低版本的协议中不存在)并且默认情况下 j7 禁用 TLS1.2(和 1.1)客户端。

HttpsURLConnection如果您明确使用(例如)连接到此 API,new URL("https://something").openConnection()则可以调整套接字工厂以在套接字上SSLContext.getInstance("TLSv1.2")明确使用和/或setEnabledProtocols。如果您使用其他中间件,例如 Apache HttpComponents,通常会有类似的方法,但它们在细节上有所不同;您需要向我们展示代码,这可能属于 StackOverflow,而不是这里。如果您正在调用内部进行连接的库,它可能有选项,也可能没有。对于所有或许多调用方法,您可以更改默认值,例如SSLContext.setDefault()HttpsURLConnection.setDefaultSSLSocketFacfory() 如果相关代码中不会覆盖这些默认值进行这样的全局更改不会对在同一 JVM 中运行的任何其他程序造成麻烦。

或者(还有更多主题!)如果您有足够新的 j7 更新,我很确定他们反向移植了系统属性,jdk.tls.client.protocols您可以将其设置为例如TLSv1,TLSv1.1,TLSv1.2更改默认值而无需更改代码(但同样,只有在未被覆盖且不损害其他任何内容的情况下)。我不记得这是什么时候,但肯定是在 7u80 之后,所以您只能通过付费 Oracle 支持或其他人付费或免费支持的 OpenJDK 来使用它。这很容易尝试可能工作。

答案2

我终于找到了一个解决方法,虽然有点丑陋。我创建了一个 Groovy 脚本,向外部 API 发出 cURL 请求。由于 cURL 可以使用最新的证书,因此我可以绕过因使用旧 JDK 而产生的限制。虽然有点笨拙,但确实有效。

相关内容