首页 > 解决方案 > 如何生成 Java PKCS12 存储以连接到常规 SSL 网站?

问题描述

我们使用常规购买的 SSL 证书通过 https 运行标准 Web API。我们的客户只是通过 https 访问它,证书是通过默认系统 RootCA 信任的。

新客户端正在使用需要 PKCS12 密钥库中的证书的 Java 通信服务器。我们如何从我们的 key/csr/crt/pem 文件生成 PKS12 密钥库?

我做了一些研究,大多数例子都需要私钥。当然,我不想与客户共享我们的私钥。

是否可以在没有私钥的情况下创建 PKCS12 密钥库,类似于浏览器中的标准 RootCA?

谢谢,蓝豹

标签: javasslpublic-key-encryptionpkcs#12

解决方案


是的。

尽管 PFX-now-PKCS12 主要设计用于将私钥证书以及链证书作为一个块存储或传输,并且最常用于此目的,但它能够存储一个或多个“单独”证书不匹配任何私钥。你是正确的,想要连接到你的客户端应该在他们的信任库中拥有你的服务器证书链的根证书,或者你的服务器证书本身,但绝对不是你的私钥。

openssl 居然可以创建这样的PKCS12:

 openssl pkcs12 -export -in certfile.pem [-name $name] -nokeys -out blah.p12 
 # if you don't specify -name it defaults to 1 (the digit one) which can be mildly confusing
 # instead of being prompted for the password you can use -passout with several forms
 # described on the openssl man page, but consider the warning below

但是,如果他们使用标准 (Sun/Oracle/OpenJDK) 加密提供程序,结果将在 Java 中不起作用,该加密提供程序(在 8+ 中)仅支持 PKCS12 中的单独证书作为 Java 中的“trustedCert”条目) certbag 有一个特殊的 Sun 定义的属性,Java 提供者在创建此类文件时会写入该属性,但 OpenSSL 没有。

而是在 8 中使用 Java 的 keytool:

jre8/bin/keytool -importcert -keystore blah.p12 -storetype pkcs12 -file $certfile [-alias $name]

或者在 9+ 中,pkcs12 现在是默认值:

jre9+/bin/keytool -importcert -keystore blah.p12 -file $certfile [-alias $name]

如果您不指定别名,则默认为mykey. 在这两种情况下,您都可以添加-storepass $pw以避免被提示,但结果密码将显示在您的屏幕上,在您的 shell 或其他命令处理器的命令历史记录中,它有一个,并且在大多数情况下其他进程运行同时在您的系统上,(任何)这可能是一个安全问题或不是。您还可以添加-noprompt以避免确认提示。

但是 user207421 是(大致)正确的,使用这样的信任库可以破坏从他们的系统建立的其他SSL/TLS 连接,至少来自同一个 JVM,除非个别调用指定单独的、单独的信任库,并且如果他们已经编码他们会知道如何处理(并要求)更简单的证书格式,例如 PEM。


推荐阅读