在 JRE 1.8 中运行时安装 CA 根证书。0_51
Install CA root certificate at runtime in JRE 1.8.0_51
我正在使用 JRE 1.8。0_51(我无法更改它),它不包括 lib/security/cacerts
中 Let's Encrypt 的根证书(它被添加到 1.8.0_141
)
我需要在运行时添加证书,我找到了执行此操作的代码:
try {
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509");
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream keyStoreStream = getClass().getClassLoader().getResourceAsStream("j51_le_ca_cert.jks");
keyStore.load(keyStoreStream, "changeit".toCharArray());
trustManagerFactory.init(keyStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustManagers, null);
SSLContext.setDefault(sc);
} catch (Exception e) {
e.printStackTrace();
}
它运行时没有抛出任何错误,但会导致以下情况之一发生:
- LE 证书已正确安装,但会覆盖所有现有证书
- 未安装 LE 证书,所有现有证书都保留
根据系统和环境的不同,这两个事件中的哪一个似乎是任意发生的 运行。
如何才能可靠地将证书与现有证书一起安装?
根据您的问题,您似乎有以下要求:
- 无法升级Java,需要保持在 v1.8.051
- 使用默认 jdk 信任库 (cacert)
- 在运行时向现有证书添加额外的受信任证书
我认为这是可能的。您可以做的是创建两个单独的 TrustManagers 并将它们组合起来,如下所述:Registering multiple keystores in JVM。您只需要从默认的 jdk 信任库 (cacert) 创建一个信任管理器,并为您自己的信任库创建一个,其中包含一个让我们加密并将其与该主题中提到的 CompositeTrustManager 合并的信任库。这个特殊的 TrustManager 可用于创建 SSLContext。
我已将代码片段提取到库中,因此如果您不介意使用其他库,可以尝试以下代码片段:
import nl.altindag.ssl.SSLFactory;
import javax.net.ssl.SSLContext;
public class App {
public static void main(String[] args) {
SSLFactory sslFactory = SSLFactory.builder()
.withTrustMaterial("j51_le_ca_cert.jks", "changeit".toCharArray())
.withDefaultTrustMaterial()
.withSslContextAlgorithm("SSL")
.build();
SSLContext sslContext = sslFactory.getSslContext();
SSLContext.setDefault(sslContext);
}
}
您可以使用以下代码片段添加库:
<dependency>
<groupId>io.github.hakky54</groupId>
<artifactId>sslcontext-kickstart</artifactId>
<version>7.0.0</version>
</dependency>
有关完整文档和示例用法,请参阅此处:GitHub - SSLContext Kickstart
我认为升级您的 JDK 更好,但有时这是不可能的,所以我希望这个替代解决方案对您有用。
我正在使用 JRE 1.8。0_51(我无法更改它),它不包括 lib/security/cacerts
中 Let's Encrypt 的根证书(它被添加到 1.8.0_141
)
我需要在运行时添加证书,我找到了执行此操作的代码:
try {
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509");
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream keyStoreStream = getClass().getClassLoader().getResourceAsStream("j51_le_ca_cert.jks");
keyStore.load(keyStoreStream, "changeit".toCharArray());
trustManagerFactory.init(keyStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustManagers, null);
SSLContext.setDefault(sc);
} catch (Exception e) {
e.printStackTrace();
}
它运行时没有抛出任何错误,但会导致以下情况之一发生:
- LE 证书已正确安装,但会覆盖所有现有证书
- 未安装 LE 证书,所有现有证书都保留
根据系统和环境的不同,这两个事件中的哪一个似乎是任意发生的 运行。
如何才能可靠地将证书与现有证书一起安装?
根据您的问题,您似乎有以下要求:
- 无法升级Java,需要保持在 v1.8.051
- 使用默认 jdk 信任库 (cacert)
- 在运行时向现有证书添加额外的受信任证书
我认为这是可能的。您可以做的是创建两个单独的 TrustManagers 并将它们组合起来,如下所述:Registering multiple keystores in JVM。您只需要从默认的 jdk 信任库 (cacert) 创建一个信任管理器,并为您自己的信任库创建一个,其中包含一个让我们加密并将其与该主题中提到的 CompositeTrustManager 合并的信任库。这个特殊的 TrustManager 可用于创建 SSLContext。
我已将代码片段提取到库中,因此如果您不介意使用其他库,可以尝试以下代码片段:
import nl.altindag.ssl.SSLFactory;
import javax.net.ssl.SSLContext;
public class App {
public static void main(String[] args) {
SSLFactory sslFactory = SSLFactory.builder()
.withTrustMaterial("j51_le_ca_cert.jks", "changeit".toCharArray())
.withDefaultTrustMaterial()
.withSslContextAlgorithm("SSL")
.build();
SSLContext sslContext = sslFactory.getSslContext();
SSLContext.setDefault(sslContext);
}
}
您可以使用以下代码片段添加库:
<dependency>
<groupId>io.github.hakky54</groupId>
<artifactId>sslcontext-kickstart</artifactId>
<version>7.0.0</version>
</dependency>
有关完整文档和示例用法,请参阅此处:GitHub - SSLContext Kickstart
我认为升级您的 JDK 更好,但有时这是不可能的,所以我希望这个替代解决方案对您有用。