将私钥添加到密钥库

时间:2018-05-28 21:08:35

标签: ssl openssl keytool pkcs#12 jks

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

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

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

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

  1. 使用keytool从jks密钥库中提取所有证书。
  2. 使用openssl
  3. 创建了一个PKCS#12密钥库
  4. 使用keytool
  5. 重命名创建的PKCS12中的别名
  6. 使用openssl
  7. 创建另一个PKCS#12密钥库
  8. 使用keytool
  9. 重命名其他创建的PKCS#12中的别名
  10. 使用keytool
  11. 将两个密钥库合并为一个
  12. 导入非私钥密钥证书
  13. 所以整个流程如下(如果还需要的话):

    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
    

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

    无论如何都要提前感谢

1 个答案:

答案 0 :(得分:1)

  1. 您可以在-changealias步骤

  2. 上使用-name long-name short来消除pkcs12 -export步骤
  3. 对于keystore.p12keystore2.p12,您的输入为key.pem和(证书)alias.short.pem。您是否打算使用(cert)alias.long.pem作为其中一个?

  4. 在免费的Oracle Javas中,只有更高版本的j8(在java.security中设置了keystore.compat)才能读取JKS和P12密钥库,而无需指定类型。默认情况下,j7和更低版仅执行JKS,j9和更高版本仅P12。

  5. FWIW,如果您将原始JKS(使用trustedCert)转换为P12(仅限j8 +),则openssl pkcs12 -nokeys将在一次操作中输出所有可信任的内容 - 但由于您需要执行不同的操作它们,您需要将其拆分为单独的文件,或者按需执行,如:

  6.     awk '/friendlyName: short/,/-END CERT/' allcerts.pem | \
          openssl pkcs12 -export -inkey key.pem -name short -out file -passout pass:PW
        # similar for long -- or make loop
        # combine the p12s as before
        awk '/friendlyName: root/,/-END CERT/' allcerts.pem | \
          keytool -keystore file -storepass PW -importcert -file root.pem -alias root -noprompt
        # similar for ca3 -- or make loop
    

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

    或者,因为这是SO,你可以编写一个更直接地执行此操作的程序:

    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); }