使用Java commons httpclient,并从.pfx中提取cacert、cert和密钥

使用Java commons httpclient,并从.pfx中提取cacert、cert和密钥,java,ssl,curl,apache-commons-httpclient,jks,Java,Ssl,Curl,Apache Commons Httpclient,Jks,我输入了一个.pfx文件 我使用以下命令从中提取CA证书、客户端证书和密钥: openssl pkcs12 -in input.pfx -clcerts -nokeys -out client-cert.pem openssl pkcs12 -in input.pfx -out ca-cert.pem -nodes -nokeys -cacerts openssl pkcs12 -in input.pfx -nocerts -nodes -out client.key 现在,我可以使用curl

我输入了一个.pfx文件

我使用以下命令从中提取CA证书、客户端证书和密钥:

openssl pkcs12 -in input.pfx -clcerts -nokeys -out client-cert.pem
openssl pkcs12 -in input.pfx -out ca-cert.pem -nodes -nokeys -cacerts
openssl pkcs12 -in input.pfx -nocerts -nodes -out client.key
现在,我可以使用curl执行以下请求:

curl--cacert./ca-cert.pem--key./client.key--cert./client-cert.pem-i-X POST--data binary'@./my data.txt'

现在我想使用commons httpclient在Java中执行相同的请求

就我所知,我应该将我的密钥转换为“keystore.jks”和“truststore.jks”,并按如下方式使用它们:

SSLContext sslContext = SSLContexts.custom()
   .loadTrustMaterial(new File("truststore.jks"), PASS.toCharArray())
   .loadKeyMaterial(new File("keystore.jks"), PASS.toCharArray(), PASS.toCharArray())
   .build();

CloseableHttpClient client = HttpClients.custom()
    .setSSLContext(sslContext)
    .build();

HttpPost post = new HttpPost("https://my-target.url");
post.setEntity(new ByteArrayEntity(FileUtils.readFileToByteArray(new File("my-data.txt"))));
client.execute(post);
有没有更简单的方法将证书传递给POST? 如果没有,将.pfx转换为.jks的正确方法是什么

我试过了

keytool -importkeystore -srckeystore input.pfx -srcstoretype pkcs12 -destkeystore keystore.jks -deststoretype JKS
但最终以

java.security.UnrecoverableKeyException:无法恢复密钥


最终的解决方案是直接加载pfx文件,并在那里信任证书

final KeyStore store = KeyStore.getInstance("PKCS12");

try (FileInputStream stream = new FileInputStream(new File("file.pfx"))) {
    store.load(stream, PASS.toCharArray());
}
SSLContext sslContext = SSLContexts.custom()
    .loadKeyMaterial(store, PASS.toCharArray())
    .loadTrustMaterial(store, TrustSelfSignedStrategy.INSTANCE)
    .build();

(1) 您的提取命令混淆了;对于
client-cert.pem
应该是
-nokeys-clcerts
,对于
ca-cert.pem
应该是
-nokeys-cacerts
(2)httpclient+core使用JVM默认密钥库,如果您是合理最新的,那么在8u60上,默认值可以直接读取PKCS12(3)如果不是,只要您对输出(jks)使用与输入(p12)相同的密码(因为即使存储pw发生更改,密钥pw也会保留),那么
-importkeystore
就是正确的。是的,谢谢Dave,我在更改文件名发布问题时混合了提取命令。事实上,我做得对。我发现我可以将pfx文件作为“PKCS12”密钥库加载。然而,我面临“无法找到请求目标的有效认证路径”问题,这迫使我将ca证书导入java security\cacerts。有没有更简单的方法?服务器证书的CA(可能与客户端证书相同或不同)必须位于客户端的信任库中(作为受信任或私有叶);如果您使用的默认值是JRE/lib/security/cacerts,并且服务器CA不是分布在cacerts中的已建立/公共CA之一,那么您必须将其添加到cacerts中——但是您发布的代码中的
.loadTrustMaterial
调用应该使用truststore.jks而不是cacerts。不是吗?truststore.jks中有什么?@dave_thompson_085是的,谢谢,我通过将ca证书转换为jks并使用“.loadTrustMaterial”加载解决了这个问题。