在 Java 8 中读取使用 OpenJDK16 中的 keytool 创建的 PKCS12 密钥库时的 IOException
TL;DR
keytool
从 OpenJDK16 创建无法从 Java 8、9、10 和 11 读取的 PKCS12 密钥库文件。这是一个错误吗?如何创建与Java 8兼容的PKCS12密钥库?
上下文
我构建了一个 Maven 项目,它生成一个可执行的 JAR 文件,该文件必须在从版本 8 到版本 16 的任何 JRE 上运行。该 JAR 文件会生成一个 HTTPS 服务器(使用 com.sun.net.httpserver.HttpsServer)。
在构建过程中,我使用生成密钥对并将其存储在捆绑在JAR中的PKCS12密钥库中(实际上,我使用的是keytool-maven-plugin):keytool
$ /path/to/jdk16/bin/keytool -genkeypair -keystore /tmp/keystore.p12 -storepass password -storetype PKCS12 -alias https -dname "CN=localhost, OU=My HTTP Server, O=Sentry Software, C=FR" -keypass password -validity 3650 -keyalg RSA -sigalg SHA256withRSA
Java 代码使用此自动生成的密钥库来启动 HTTPS 服务器:
// initialize the HTTPS server
httpsServer = HttpsServer.create(socketAddress, 0);
// initialize the keystore
KeyStore keyStore = KeyStore.getInstance("PKCS12");
// Load the self-certificate that is bundled with the JAR (see pom.xml)
InputStream ksStream = this.getClass().getResourceAsStream("/keystore.p12");
keyStore.load(ksStream, "password".toCharArray()); // Exception here
// Rest of the code (only for context purpose)
// setup the key manager factory
String defaultKeyManagerAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(defaultKeyManagerAlgorithm);
keyManagerFactory.init(keyStore, "password".toCharArray());
// setup the trust manager factory
String defaultTrustManagerAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(defaultTrustManagerAlgorithm);
trustManagerFactory.init(keyStore);
// setup the HTTPS context and parameters
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
// Sets the default SSL configuration (no need for extra code here!)
httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext));
问题
当JAR使用OpenJDK 16 JDK构建时(并且使用OpenJDK 16),然后在Java 8 JRE中执行,我们在以下位置得到这个异常:keytool
keyStore.load()
IOException: parseAlgParameters failed: ObjectIdentifier() -- data isn't an object ID (tag = 48)
当在 OpenJDK 11.0.7+10 中执行相同的 JAR 时,我们得到以下异常:
IOException: Integrity check failed: java.security.NoSuchAlgorithmException: Algorithm HmacPBESHA256 not available
但是,当使用OpenJDK 14,15或16执行相同的JAR时,没有例外,一切都可以正常工作。
下表总结了 的版本,以及是否可以在各种 JRE 版本中加载使用 的每个版本创建的 PKCS12 密钥存储:keytool
keytool
杰瑞 8 | JRE 11 | 杰瑞 14 | 杰瑞 16 | |
---|---|---|---|---|
键盘工具 8 | ✅ | ✅ | ✅ | ✅ |
键工具 11 | ✅ | ✅ | ✅ | ✅ |
键工具 14 | ✅ | ✅ | ✅ | ✅ |
键工具 15 | ✅ | ✅ | ✅ | ✅ |
键工具 16 | ⛔ | ⛔ | ✅ | ✅ |
问题
这是 中的错误,还是 KeyStore 类中的错误?keytool
如何使用OpenJDK16创建一个PKCS12密钥存储,该密钥存储将在与JRE 8一起加载时工作?
什么是HmacPBESHA256?我没有在命令行中指定此算法。keytool