小编典典
听起来您面临与此问题类似的问题,因为null用于in的trustmanager参数可SSLContext.init(...)还原为默认的信任管理器,而不适用于密钥管理器。
话虽如此,使用默认系统属性初始化KeyManager并不难。这样的事情应该可以工作(直接在此答案中编写的代码,因此您可能需要修复一些小问题):
String provider = System.getProperty("javax.net.ssl.keyStoreProvider");
String keystoreType = System.getProperty("javax.net.ssl.keyStoreType", KeyStore.getDefaultType());
KeyStore ks = null;
if (provider != null) {
ks = KeyStore.getInstance(keystoreType, provider);
} else {
ks = KeyStore.getInstance(keystoreType);
}
InputStream ksis = null;
String keystorePath = System.getProperty("javax.net.ssl.keyStore");
String keystorePassword = System.getProperty("javax.net.ssl.keyStorePassword");
if (keystorePath != null && !"NONE".equals(keystorePath)) {
ksis = new FileInputStream(keystorePath);
}
try {
ks.load(ksis, keystorePassword.toCharArray());
} finally {
if (ksis != null) { ksis.close(); }
}
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, keystorePassword.toCharArray());
// Note that there is no property for the key password itself, which may be different.
// We're using the keystore password too.
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), ..., null);
(更具体地说,也可能是该实用程序类感兴趣的类getKeyStoreDefaultLoader()。)
编辑:( 在您的其他评论之后)
恐怕您只想自定义一半的Oracle和IBM JSSE似乎都没有默认行为SSLContext。您在Oracle JSSE文档中链接到的部分说:“
_如果javax.net.ssl.keyStore系统属性和相应的javax.net.ssl.keyStorePassword系统属性指定了密钥库,则默认SSLContext创建的KeyManager将是用于管理指定密钥库的KeyManager实施。_
“由于您使用的是custom SSLContext,无论如何都不是默认值(即使您要自定义其中的一部分),因此在这里并不会真正应用。
无论如何,Oracle JSSE参考指南和IBM
JSSE参考指南在此主题上有所不同。(我不确定这其中有多少是“标准的”,以及一个原则上是否应该与另一个相容,但是显然不是这种情况。)
这两个“ 创建SSLContext对象 ”部分是 几乎 相同的,但它们是不同的。
如果KeyManager []参数为null,则将为此上下文定义一个空的KeyManager。
如果KeyManager
[]参数为null,则将在安装的安全提供程序中搜索KeyManagerFactory的最高优先级实现,从中将获取适当的KeyManager。
不幸的是,如果您希望具有不同规范的实现之间具有相同的行为,则即使要有效地复制其中一个实现已经执行的操作,也必须编写一些代码。
2020-11-16