【问题标题】:Creating .p12 truststore with openssl使用 openssl 创建 .p12 信任库
【发布时间】:2017-08-03 15:56:16
【问题描述】:

我正在编写一个 Java 8 应用程序,并希望使用自签名证书设置一个简单的密钥库和信任库。

通常情况如下:

  1. 使用 openssl 创建密钥对 + 证书。
  2. 使用keytool 创建一个 .jks 密钥库 + .jks 信任库

现在我只想使用 openssl 并创建 .p12 密钥库而不是 .jks 密钥库。

使用以下命令创建 .p12 密钥库效果很好:

# Create private key and certificate
openssl req -x509 -newkey rsa:"${rsa}" -sha256 \
    -keyout "${key}" \
    -out "${cert}" \
    -days "${days}"

# Create .p12 keystore
openssl pkcs12 -export -in "${cert}" -inkey "${key}" -out "${keystore}"

此密钥库似乎工作正常,因为在我的 Java 应用程序中提供相应的 .jks 信任库将使 TLS 连接正常运行。但是我无法让 .p12 信任库正常工作。

我尝试按照here 的建议创建信任库:

# Create .p12 truststore
openssl pkcs12 -export -nokeys -in "${cert}" -out "${truststore}"

然后像这样加载它:

FileInputStream fis = new FileInputStream(new File(trustorePath));
KeyStore trustStore = KeyStore.getInstance("PKCS12");
trustStore.load(fis, truststorePassword.toCharArray());
fis.close();

但我在我的 java 代码中收到以下异常:

意外错误:java.security.InvalidAlgorithmParameterException: trustAnchors 参数必须为非空

任何想法我做错了什么?

(非常感谢使用带有 Java 8 的 .p12 信任库的工作 sn-p。)

【问题讨论】:

  • 信任库通常不包含私钥。可能这会让 Java 感到困惑吗?如果不需要,请删除私钥或再次添加没有私钥的证书。
  • 我试过你的截图,它使用 openssl 0.9.8zh 和 oracle jdk 1.8.0_121 工作,很奇怪
  • keytool 可能是一个更容易使用的工具。

标签: java ssl openssl


【解决方案1】:

对此行为的可能解释:

Java 7 之前的标准 PKCS#12 提供程序不允许受信任 证书条目。 JSSE 参考指南是这样说的:

不支持在 PKCS12 密钥库中存储受信任的证书。 PKCS12 主要用于传递与相关联的私钥 证书链。它没有任何“受信任”的概念 证书。在互操作性方面,其他 PKCS12 供应商已经 相同的限制。 Mozilla 和 Internet Explorer 等浏览器 不接受仅包含受信任证书的 PKCS12 文件。

这在 Java 8 中有所改变,它支持受信任的证书 在 PKCS#12 - 如果它们标记有特殊属性(OID 2.16.840.1.113894.746875.1.1):

openssl pkcs12 -in microsoft.p12 -info
MAC Iteration 1024
MAC verified OK
PKCS7 Encrypted data: pbeWithSHA1And40BitRC2-CBC, Iteration 1024
Certificate bag
Bag Attributes
    friendlyName: microsoft it ssl sha2 (baltimore cybertrust root)
    2.16.840.1.113894.746875.1.1: <Unsupported tag 6>

来源:

【讨论】:

  • 我在“1.8.0_171”上,不再需要这个魔法属性。在信任管理器中使用时,添加到 PKCS12 存储的所有条目都是受信任的。
  • 我在“1.8.0_171”上,这不起作用,只包含证书的 PKCS12 给出“trustAnchors 参数必须为非空”错误
【解决方案2】:

我还没有找到使用 openssl 的方法,但我找到了使用 keytool(OpenJDK 套件的一部分)的方法。

我需要创建一个密钥库,其中包含具有2.16.840.1.113894.746875.1.1: &lt;Unsupported tag 6&gt; 属性的 CA 证书和一个附加证书及其不带此属性的密钥。我想与其他人分享解决方案,他们将通过谷歌搜索openssl "2.16.840.1.113894.746875.1.1" 找到此页面 :-)

此命令使用具有2.16.840.1.113894.746875.1.1: &lt;Unsupported tag 6&gt; 属性的 CA 证书(假设您已经有一个 CA)创建一个 PKCS12:

keytool -storepass '***' -import -alias ca -file ***/ca.crt.pem -keystore ***/ca.p12 -deststoretype PKCS12

此命令将额外的 PEM 编码证书及其私钥转换为 PKCS12:

openssl pkcs12 -in ***/additional.cert.pem -inkey ***/additional.key.pem -name additional -export -out ***/additional.p12

此命令将包含 CA 证书的 PKCS12 密钥库合并到包含附加密钥及其私钥的 PKCS12 密钥库:

keytool -importkeystore -srckeystore ***/ca.p12 -srcstoretype pkcs12 -srcstorepass '***' -destkeystore ***/additional.p12 -deststoretype pkcs12 -deststorepass '***'

【讨论】: