Openssl 将CA签名的JKS密钥库转换为PEM

Openssl 将CA签名的JKS密钥库转换为PEM,openssl,keystore,keytool,pem,jks,Openssl,Keystore,Keytool,Pem,Jks,我有一个JKS密钥库,证书由CA签署。我需要将其导出为PEM格式,以便与nginx一起使用。我需要这样做,它包括整个链,以便我的客户可以验证签名 如果我这样做: keytool -exportcert -keystore mykestore.jks -file mycert.crt -alias myalias openssl x509 -out mycert.crt.pem -outform pem -in mycert.crt -inform der 它只包括最低级别的证书。验证失败: $

我有一个JKS密钥库,证书由CA签署。我需要将其导出为PEM格式,以便与nginx一起使用。我需要这样做,它包括整个链,以便我的客户可以验证签名

如果我这样做:

keytool -exportcert -keystore mykestore.jks -file mycert.crt -alias myalias
openssl x509 -out mycert.crt.pem -outform pem -in mycert.crt -inform der
它只包括最低级别的证书。验证失败:

$ openssl s_client -connect localhost:443
CONNECTED(00000003)
depth=0 /O=*.mydomain.com/OU=Domain Control Validated/CN=*.mydomain.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 /O=*.mydomain.com/OU=Domain Control Validated/CN=*.mydomain.com
verify error:num=27:certificate not trusted
verify return:1
depth=0 /O=*.mydomain.com/OU=Domain Control Validated/CN=*.mydomain.com
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
 0 s:/O=*.mydomain.com/OU=Domain Control Validated/CN=*.mydomain.com
   i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certificates.godaddy.com/repository/CN=Go Daddy Secure Certification Authority/serialNumber=123123
... (only one certificate!)
...
SSL-Session:
    ...
    Verify return code: 21 (unable to verify the first certificate)
来自Java:

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
而具有相同JKS密钥库的Jetty打印以下内容:

$ openssl s_client -connect localhost:8084
CONNECTED(00000003)
depth=2 /C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
verify error:num=19:self signed certificate in certificate chain
verify return:0
---
Certificate chain
 0 s:/O=*.mydomain.com/OU=Domain Control Validated/CN=*.mydomain.com
   i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certificates.godaddy.com/repository/CN=Go Daddy Secure Certification Authority/serialNumber=1234
 1 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certificates.godaddy.com/repository/CN=Go Daddy Secure Certification Authority/serialNumber=1234
   i:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
 2 s:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
   i:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
...
SSL-Session:
    Verify return code: 19 (self signed certificate in certificate chain)
尽管openssl返回了19个错误,但对于Java
HttpsURLConnection
来说,这不再是一个问题,这就是我所关心的


那么,如何从JKS导出整个链,以一种可与nginx服务器和Java客户端一起使用的格式(例如PEM)?我遗漏了什么?

我不确定是否可以使用
keytool
提取链,但可以通过一个小型Java程序完成:

public void extract(KeyStore ks, String alias, char[] password, File dstdir) throws Exception
{
    KeyStore.PasswordProtection pwd = new KeyStore.PasswordProtection(password);
    KeyStore.PrivateKeyEntry entry = (KeyStore.PasswordKeyEntry)ks.getEntry(alias, pwd);
    Certificate[] chain = entry.getCertificateChain();
    for (int i = 0; i < chain.length; i++) {
        Certificate c = chain[i];
        FileOutputStream out = new FileOutputStream(new File(dstdir, String.format("%s.%d.crt", alias, i)));
        out.write(c.getEncoded());
        out.close();
    }
}
public void extract(密钥库ks、字符串别名、char[]密码、文件dstdir)引发异常
{
KeyStore.PasswordProtection pwd=新KeyStore.PasswordProtection(密码);
KeyStore.PrivateKeyEntry=(KeyStore.PasswordKeyEntry)ks.getEntry(别名,pwd);
证书[]链=entry.getCertificateChain();
对于(int i=0;i

这段代码应该在提交的目录中以DER格式写入链的所有证书。

我经常遇到的一个相当大的问题是,在生成CSR以获取我们的证书时,密钥库(Sun格式的jks密钥库)不输出.key或提供任何获取.key的工具。因此,我总是以一个.pem/.crt结束,它无法与Apache2一起使用,Apache2不能像Tomcat那样读取JKS密钥库,而是需要一个未打包的.key+.pem/.crt对

首先,获取现有密钥库的“副本”并跳到下面的第5个命令,或者像这样创建自己的密钥库:

C:\Temp>keytool -genkey -alias tomcat -keyalg RSA -keystore
 keystore.jks -keysize 2048 -validity 730 -storepass changeit
然后(可选)创建一个2年CSR,然后在下一个3步过程中导入CSR响应:

C:\Temp>keytool -certreq -alias mydomain -keystore keystore.jks
 -file mydomain.csr
C:\Temp>keytool -import -trustcacerts -alias root -file
 RootPack.crt -keystore keystore.jks -storepass changeit
C:\Temp>keytool -import -trustcacerts -alias tomcat -file mydomain.response.crt
 -keystore keystore.jks -storepass changeit
要使其正常工作,并且如果您已经拥有用于Tomcat应用程序服务器的JKS密钥库文件,请执行以下步骤:

首先,将DER(二进制)格式的证书放入名为“exported DER.crt”的文件中:

C:\Temp>keytool -export -alias tomcat -keystore keystore.jks -file
 exported-der.crt
然后,查看并验证它:

C:\Temp>openssl x509 -noout -text -in exported-der.crt -inform der
现在,您需要将其转换为PEM格式,PEM格式在Apache等应用程序中得到更广泛的应用,并由OpenSSL进行PKCS12转换:

C:\Temp>openssl x509 -in exported-der.crt -out exported-pem.crt 
-outform pem -inform der
然后,下载并使用ExportPriv从密钥库获取未加密的私钥:

C:\Temp>java ExportPriv <keystore> <alias> <password> > exported-pkcs8.key

您可以轻松地将JKS文件转换为PKCS12文件:

keytool -importkeystore -srckeystore keystore.jks -srcstoretype JKS -deststoretype PKCS12 -destkeystore keystore.p12
然后,您可以通过以下方式提取私钥和任何证书:

openssl pkcs12 -in keystore.p12

你问的最后一个问题的答案在下面我的答案的末尾。这是一个很好的答案-它怎么没有更多的投票权?同意,我真不敢相信这有多好。
openssl pkcs12 -in keystore.p12