gpt4 book ai didi

java - 如何在新的(未弃用的)SSLSocketFactory 中加载私钥密码?

转载 作者:行者123 更新时间:2023-11-29 04:05:46 31 4
gpt4 key购买 nike

我当前的 TCP 客户端正在使用 org.apache.http.conn.ssl.SSLSocketFactory
构建套接字我正在迁移到 import javax.net.ssl.SSLSocketFactory;但是,我不确定如何加载存储在我已有的 .p12 文件中的客户端证书的私钥,作为新 SSLSocketFactory 的上下文?

这是我现有的代码,使用已弃用的 SSLSocketFactory:

import org.apache.http.ssl.SSLContexts;
import org.apache.http.conn.ssl.SSLSocketFactory;

String ksPassphrase = "myKSpass";
String pkPassphrase = "myPKpass";
// Get a keystore instance of type PKCS12:
KeyStore keystore = KeyStore.getInstance("PKCS12");
// Load keystore file and password:
keystore.load(new FileInputStream("myFile.p12"), ksPassphrase.toCharArray());
// Create HTTPS connection socket factory context:
SSLContext context = SSLContexts.custom()
.loadKeyMaterial(keystore, pkPassphrase.toCharArray())
.build();

SSLSocketFactory sslScktFactory = new SSLSocketFactory(context);

这是我可以从文档中管理的最佳代码:

import javax.net.ssl.*;

// not sure if this is the pass to KS or private key or, somehow both?
String passphrase = "myPassphrase"

SSLContext context = SSLContext.getInstance("TLS");
KeyManagerFactory keyMngFactory = KeyManagerFactory.getInstance("SunX509");
KeyStore keyStore = KeyStore.getInstance("JKS");

keyStore.load(new FileInputStream("myFile.jks"), passphrase.toCharArray());
keyMngFactory.init(keyStore, passphrase);
context.init(keyMngFactory.getKeyManagers(), null, null);

SSLSocketFactory sslScktFactory = context.getSocketFactory();
  • 我认为问题在于我没有.custom() 方法用于新库下的上下文。
    新的 SSLSocketFactory 使用什么?
  • 是不是 JKS keystore 没有存储私钥的内部密码(直到现在我只使用 PKCS,不熟悉 JKS 格式),这就是为什么我看不到私钥密码的原因正在被提及?

最佳答案

您传递给 KeyStore.load(InputStream,char[]) 的密码是存储密码;您传递给 KeyManagerFactory.init(KeyStore,char[]) 的密码是私钥密码('the' 单数;如果有多个 key ,则所有 key 都必须相同)并注意它是char[] 而不是 String —— 您的编译器(或 IDE)应该已经告诉您了。如果您想继续使用现有(或任何其他/新的)PKCS12 文件,则需要更改新代码以使用 KeyStore.getInstance("PKCS12")

请注意,API 允许您使用与 storepass 不同的 key 密码,但您可能希望与之交换或共享 PKCS12 文件的其他软件(如 Windows、MacOSX、OpenSSL,我认为是 NSS) 支持这一点,并尽量避免此类问题,Java 的命令行 keytool 不会将 keypass 设置为不同于 PKCS12 的 storepass

What to use for the new SSLSocketFactory?

SSLContext.getSocketFactory() - 与您发布的完全一样。事实上,这实际上是您之前弃用的 org.apache.http.conn.ssl.SSLSocketFactory.SSLSocketFactory(SSLContext) 在内部所做的,只是它还默认了 HostNameVerifier。

Is it the case that JKS keystores don't have internal passwords for the private keys stored inside (I only used PKCS until now, not familiar with the JKS format) and that's why I can't see where the private key password is being referred to?

没有; JKS 商店确实有单独的 storepass 和 keypass,如果按照我上面的描述进行更正,它们将在您发布的代码中使用——尽管私钥加密 JKS 使用 keypass for 比通常的要弱在 PKCS12 中使用。由于 JKS 文件无论如何都不能与其他软件互操作,keytool 确实支持使用与 storepass 不同的 keypass。事实上,keytool(通常是 JCA)支持在一个 JKS 存储中为不同的私钥设置不同的 keypass 值,但是 KeyManagerFactory(用于 SSL/TLS,即 JSSE)不支持 支持这一点,Apache 也不支持(除了添加/包装关键选择策略之外,它只是在底层使用 JSSE)。

(OP) 编辑:这是根据您的建议生成的一些经过测试的代码:

// Consider having both the same, for compatibility with Windows/MacOSX/OpenSSL/etc:
String ksPassphrase = "myKSpass";
String pkPassphrase = "myPKpass";

SSLContext context = SSLContext.getInstance("TLS");
KeyManagerFactory keyMngFactory = KeyManagerFactory.getInstance("SunX509");
KeyStore keyStore = KeyStore.getInstance("PKCS12");

keyStore.load(new FileInputStream("myFile.p12"),
ksPassphrase.toCharArray());
keyMngFactory.init(keyStore, pkPassphrase.toCharArray());
context.init(keyMngFactory.getKeyManagers(), null, null);

SSLSocketFactory sslScktFactory = context.getSocketFactory();

关于java - 如何在新的(未弃用的)SSLSocketFactory 中加载私钥密码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58863766/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com