具有多个 key 和不同密码的 Java keystore

标签 java ssl networking

我创建了一个 java JKS keystore :

keytool -genkey -alias mydomain -keyalg RSA -keystore mytest.jks -keysize 2048

之后,我使用服务器的 CRT 和 openssl 创建了一个 P12 文件:
openssl pkcs12 -export -in server.crt -inkey server.key > server.p12

现在我将 P12 文件导入到我之前创建的 JKS keystore 中:
keytool -importkeystore -srckeystore server.p12 -destkeystore mytest.jks -srcstoretype pkcs12

它有效,我可以使用这个 JKS 来初始化与服务器的 SSL 连接:
public static SSLContext initSSLContext(String keystoreLocation, String keystorePwd, String truststorePwd, String serverCrtPwd)
SSLContext context;
context = SSLContext.getInstance("TLS");
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(keystoreLocation), keystorePwd.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, serverCrtPwd.toCharArray());

KeyStore trustStore = KeyStore.getInstance("jks");
trustStore.load(new FileInputStream(keystoreLocation), truststorePwd.toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);

context.init(kmf.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());

将导入的 CRT 文件的 keystore 位置、密码和密码放入其工作的参数中。

现在我必须将多个 P12 文件转换并导入到同一个 JKS keystore 中,多次运行导入部分,我有多个使用不同别名导入的 key ,当然还有不同的密码。我的问题是现在每个导入的 key 都有自己的密码。
我只想使用给定 keystore 中的每个可用别名初始化 SSL 连接一次。因为更多的服务器将使用 SSL 将数据发送到我的应用程序,它们具有不同的密码,它们被导入我的 keystore ,但我无法使用多个密码初始化我的 keystore ,它只接受一个密码。如何使用多个具有不同别名和不同密码的导入 P12 来初始化我的 keystore ? init 方法只接受一个用于“从 keystore 恢复 key ”的参数。

谢谢!

最佳答案

最近我遇到了同样的挑战来实现这一目标。在寻找解决方案时,我遇到了您的问题。也许我晚了 5 年,但在找到解决方案后,我想与您分享。
所以我发现你有几个选择:

  • 所有 key 应具有相同的密码,或
  • 用它自己的 KeyManager 或
  • 为每个键实例化一个单独的 SSLContext

    显然您已经知道这些选项并且您不想执行这些操作。另一种方法是仍然拥有一个具有不同 key 和密码的 keystore 。假设您有一个 keystore ,其中包含具有以下别名和密码的 key :
  • foo -> foo-password
  • bar -> bar-password
  • lorum-ipsum -> lorum-ipsum-password

  • 以下设置将为您解决问题:
    var sslContext = SSLContext.getInstance("TLS");
    var keyStore = ... // your custom KeyStore
    
    var keyManager = KeyManagerUtils.createKeyManager(keyStore, Map.of(
            "foo","foo-password".toCharArray(),
            "bar","bar-password".toCharArray(),
            "lorum-ipsum","lorum-ipsum-password".toCharArray()
    ));
    
    sslContext.init(new KeyManager[]{keyManager}, trustManagers, null);
    
    这个 KeyManagerUtils 在幕后所做的是为每个 key /密码创建一个 KeyManager 并将其合并到一个基础 KeyManager 中,该基础 KeyManager 能够包含多个 KeyManager 并将其作为单个返回,以便您可以在 SSLContext 中使用它。详情和用法见这里:Github - SSLContext-Kickstart

    关于具有多个 key 和不同密码的 Java keystore ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35709433/

    相关文章:

    java - 使用 selenium webdriver junit 测试自动化 saksfifthavenue.com 时无法关闭弹出窗口

    java - 加载 keystore 文件,找不到别名

    java - Sonatype OSS 索引分析器请求组件错误报告 javax.net.ssl.SSLHandshakeException :

    c - openSSL:如何创建 CA 文件

    java - 什么以及为什么是 Java 6 和 Java 7?

    java - 将代码从使用计时器移植到预定执行器服务

    java - 如何使用 Spring 配置基于属性文件配置一个实现?

    ruby - 如果运行了 tls_start,EventMachine 会在 close_connection 上发出 close_notify 吗?

    c++ - boost.asio 和当前的网络 TS 最大的区别是什么?

    java - 检查DataInputStream是否有内容