当前位置: 首页 > 面试题库 >

在使用Java中的默认KeyStore(JSSE)时如何提供特定的TrustStore

雍飞雨
2023-03-14
问题内容

JSSE允许用户通过指定javax.net.ssl。*参数来提供默认的信任库和密钥库。我想为我的应用程序提供一个非默认的TrustManager,同时允许用户照常指定KeyManager,但是似乎没有任何方法可以实现此目的。

细节

http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html#CustomizingStores

假设在unix机器上,我希望允许用户使用pkcs12密钥库进行身份验证,而在OS XI上,希望允许用户使用系统密钥链。在OS
X上,可以按以下方式启动应用程序:

java -Djavax.net.ssl.keyStore=NONE -Djavax.net.ssl.keyStoreType=KeychainStore \
     -Djavax.net.ssl.keyStorePassword=- -jar MyApplication.jar

这将很好地工作:当应用程序访问需要相互身份验证(客户端证书身份验证)的https服务器时,系统将提示用户允许访问其钥匙串。

问题

现在假设我想将一个自签名证书颁发机构与我的应用程序捆绑在一起。我可以通过构造TrustManagerFactory并传入包含我的证书(javadoc)的KeyStore来覆盖默认的信任管理器。但是,要使用此非默认信任管理器,我需要创建并初始化SSLContext。问题就在这里。

通过调用init(..)并同时传递K​​eyManager和TrustManager
来初始化SSLContext 。但是,使用javax.net.ssl。*参数创建KeyManager的逻辑嵌入在默认SSLContexts的实现中-
我无法找到一种使用默认行为来获取KeyManager或KeyManagerFactory的方法,同时还指定了非默认的TrustManager或TrustManagerFactory。因此,似乎不可能使用例如适当的操作系统特定的钥匙串实现,同时还提供用于验证远程服务器的根证书。


问题答案:

听起来您面临与此问题类似的问题,因为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对象 ”部分是 几乎 相同的,但它们是不同的。

《Oracle
JSSE参考指南》指出:

如果KeyManager []参数为null,则将为此上下文定义一个空的KeyManager。

在IBM
JSSE参考指南说:

如果KeyManager
[]参数为null,则将在安装的安全提供程序中搜索KeyManagerFactory的最高优先级实现,从中将获取适当的KeyManager。

不幸的是,如果您希望具有不同规范的实现之间具有相同的行为,则即使要有效地复制其中一个实现已经执行的操作,也必须编写一些代码。



 类似资料:
  • JSSE允许用户通过指定javax.net.ssl.*参数来提供默认的信任存储和密钥存储。我想为我的应用程序提供一个非默认的TrustManager,同时允许用户像往常一样指定KeyManager,但是似乎没有任何方法可以实现这一点。 http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.h

  • 如果我创建一个提供者并将其绑定到一个类,就像这样 然后

  • 问题内容: 在Swift中处理可选选项的习惯用法似乎过于冗长,如果您只想在nil为零的情况下提供默认值,则它是: 涉及不必要地复制代码,或 这不需要是常数。 Scala的Option monad(与Swift的Optional基本相同)具有用于此目的的方法: 我想念什么吗?Swift已经有一种紧凑的方式做到这一点吗?否则,是否可以在扩展名中为Optional 定义? 问题答案: 更新资料 苹果现在

  • 为我在原始问题中提出的错误代码示例道歉。我试图把我的问题简单化,但结果却相当令人困惑。 我稍微修改了一下代码: 我得到了第一个错误: 所以我把最后一行改为: 然后在Orelse上弹出一个新的错误: Optional>类型中的方法orElse(Capture#4-of?extends Map.Entry)不适用于参数(AbstractMap.SimpleEntry) 我最初的问题是,我不知道如何为这

  • 在Java8上运行的一小部分示例代码中,我试图遵循bc-fips-1.0.2.jar用户指南Legion of the Bouncy Castle Inc. BC-FJA 1.0.2(Bouncy Castle FIPSJavaAPI)用户指南Date: 09/14/19: 注意:对FIPS模式的支持在Java 1.9中似乎已经开始消失,已经确认从Java 11开始它是一个空操作。对于Java 1

  • 但是现在我想为任何未显式设置的字段提供默认值。因此,如果我这样做了,那么将创建一个具有所有默认值的对象: