【问题标题】:adding private key to a keystore将私钥添加到密钥库
【发布时间】:2018-11-07 11:08:00
【问题描述】:

为了更新某些证书,我必须将 jks 密钥库转换为 PKCS#12 密钥库,并在转换过程中包含私钥。我们收到的密钥库是 JKS 密钥库,但是我们的网络服务器使用 PKCS#12 密钥库,我们收到的密钥库只包含证书而不是私钥。

我试图用谷歌搜索并阅读 SO 的几个条目,但我只提出了一个解决方案,这似乎更像是一种解决方法而不是一种好方法,所以我想知道是否有人有更好的方法来解决注入私钥并以更简单的方式从 jks 密钥库转换为 PKCS#12 密钥库。

似乎JKS密钥库只能由keytool操作,但是keytool实用程序不支持将私钥注入trustedCertEntries AFAIK,所以我使用的方法如下:

假设我将私钥作为 pem 文件。

  1. 使用 keytool 从 jks 密钥库中提取了所有证书。
  2. 使用 openssl 创建了一个 PKCS#12 密钥库
  3. 使用 keytool 重命名创建的 PKCS12 中的别名
  4. 使用 openssl 创建另一个 PKCS#12 密钥库
  5. 使用 keytool 重命名另一个创建的 PKCS#12 中的别名
  6. 使用 keytool 将两个密钥库合并为一个
  7. 导入非私钥证书

所以整个流程如下(以防万一也需要):

openssl pkcs12 -in orig.alias.p12 -nodes -nocerts -out key.pem -passin pass:PASSWORD
keytool -keystore keystore1 -storepass PASSWORD -list
keytool -keystore keystore1 -storepass PASSWORD -rfc -file alias.root.pem -alias "root" -exportcert
keytool -keystore keystore1 -storepass PASSWORD -rfc -file alias.ca3.pem -alias "ca3" -exportcert
keytool -keystore keystore1 -storepass PASSWORD -rfc -file alias.long.pem -alias "long" -exportcert
keytool -keystore keystore1 -storepass PASSWORD -rfc -file alias.short.pem -alias "short" -exportcert
openssl pkcs12 -export -out keystore.p12 -inkey key.pem -in alias.short.pem -passout pass:PASSWORD
keytool -changealias -alias "1" -destalias "short" -keypass PASSWORD -keystore keystore.p12 -storepass PASSWORD
openssl pkcs12 -export -out keystore2.p12 -inkey key.pem -in alias.long.pem -passout pass:PASSWORD
keytool -changealias -alias "1" -destalias "long" -keypass PASSWORD -keystore keystore2.p12 -storepass PASSWORD
keytool -importkeystore -srckeystore keystore2.p12 -srcstoretype pkcs12 -srcstorepass PASSWORD -destkeystore keystore.p12 -deststoretype pkcs12 -deststorepass PASSWORD
keytool -keystore keystore.p12 -storepass PASSWORD -file alias.ca3.pem -alias "ca3" -importcert -noprompt
keytool -keystore keystore.p12 -storepass PASSWORD -file alias.root.pem -alias "root" -importcert  -noprompt
keytool -keystore keystore.p12 -storepass PASSWORD -list

例如,我想象如果我可以在导入私钥证书时设置别名,那么之后我就不需要重命名别名了。那可能吗?

无论如何提前谢谢

【问题讨论】:

  • 我假设您只需要这样做一次(或者可能一年一次)。在这种情况下,恕我直言,基于 GUI 的程序比坏的旧 keytool 简单得多。我建议使用开源软件KeyStore Explorer。 AFAIR 它应该能够加载 JKS 密钥库并将其保存为 PKCS#12。
  • 这里有一些严重错误。如果您将私钥发送给其他任何人,您已经对其造成了致命的危害。从他们没有归还的事实看来,他们一开始就不需要它。在任何情况下,您现在需要做的就是将更新后的 证书 重新导入到已经拥有私钥的原始 JKS 密钥库中。但是您确实需要重新键入。
  • @EJP 也许我不够清楚,但私钥从未发送到另一部分。我刚刚发送了用公钥签名的 CSR,我得到了一个带有证书的 .JKS 文件..
  • @Robert 这可能是一个可行的解决方案。感谢您的建议

标签: ssl openssl keytool pkcs#12 jks


【解决方案1】:
  1. 您可以通过在pkcs12 -export 步骤上使用-name long-name short 来消除-changealias 步骤

  2. 对于keystore.p12keystore2.p12,您的输入是key.pem 和(证书)alias.short.pem。您是否打算将(证书)alias.long.pem 用于其中之一?

  3. 在免费的 Oracle Java 中,只有更高版本的 j8(在 java.security 中设置了 keystore.compat)可以在不指定类型的情况下读取 JKS 和 P12 密钥库。默认情况下,j7 及以下只做 JKS,j9 及以上只做 P12。

  4. FWIW,如果您将原始 JKS(带有trustedCert)转换为P12(仅带有j8+),那么openssl pkcs12 -nokeys 将在一次操作中输出所有trustedcerts——但是由于您需要对它们做不同的事情,您需要将其拆分为单独的文件,或者按需执行:

awk '/friendlyName: short/,/-END CERT/' allcerts.pem | \ openssl pkcs12 -export -inkey key.pem -name short -out file -passout pass:PW # 类似 for long -- 或 make loop # 像以前一样组合 p12s awk '/friendlyName: root/,/-END CERT/' allcerts.pem | \ keytool -keystore 文件 -storepass PW -importcert -file root.pem -alias root -noprompt # 类似 ca3 -- 或 make loop

...我不确定这是否真的是一种改进

或者,既然是这样,您可以编写一个更直接地执行此操作的程序:

char[] pw = "PASSWORD".toCharArray(); // or whatever as appropriate
KeyStore ks1 = KeyStore.getInstance("JKS"); ks1.load (new FileInputStream ("certs",pw));
KeyStore ks2 = KeyStore.getInstance("PKCS12"); 
try( InputStream is = new FileInputStream("oldp12") ){ ks2.load(is,pw); }
String alias = ks2.getAliases().nextElement(); // assume only one
PrivateKey key = (PrivateKey) ks2.getKey(alias,pw); 
ks2.deleteAlias(alias); 
ks2.setKeyEntry("short",key,pw,new Certificate[]{ ks1.getCertificate("short") });
ks2.setKeyEntry("long" ,key,pw,new Certificate[]{ ks1.getCertificate("long" ) });
// assuming those combinations are what you intended, see above
ks2.setCertificateEntry("root", ks1.getCertificate("root") );
ks2.setCertificateEntry("ca3" , ks1.getCertificate("ca3" ) );
try( OutputStream os = new FileOutputStream ("newp12") ){ ks2.store(os,pw); }

【讨论】:

  • 1) 是的,这确实可以为我节省两个步骤。 2)是的,你是对的。这是一个剪切和粘贴错误,但证书是相同的,只是别名不同。 3)感谢您的信息 4)也许正在简化它,但感谢您的信息 java 解决方案似乎很有趣......但我仍然惊讶于将私钥注入密钥库是如此复杂......我本来可以想象它运营团队的标准操作,但也许我错了。
  • 我会加分给你,但我需要 15 个声望点,所以我只能在 cmets 中这样做
  • 作为提问者,您可以使用复选标记来接受您认为解决了您的问题的答案 (see link)(或者如果有多个,您认为最好的答案)——这也意味着 Q不再被列为“未答复”以供其他人花时间阅读。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-15
  • 1970-01-01
  • 1970-01-01
  • 2013-08-06
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
相关资源
最近更新 更多