将 CA 签名的 JKS 密钥库转换为 PEM
我有一个带有 CA 签名证书的 JKS 密钥库。我需要将其导出为 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
的问题,这就是我所关心的。
那么,如何以适用于 nginx 服务器和 Java 客户端的格式(例如 PEM)从 JKS 导出整个链?我缺少什么?
I have a JKS keystore with certicate signed by CA. I need to export it in PEM format in order to use it with nginx. I need to do it in such a way that it includes the whole chain, so that my client can verify the signature.
If I do something like:
keytool -exportcert -keystore mykestore.jks -file mycert.crt -alias myalias
openssl x509 -out mycert.crt.pem -outform pem -in mycert.crt -inform der
It only includes the lowest level certificate. The verification fails:
$ 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)
From Java:
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Whereas Jetty with the same JKS keystore prints the following:
$ 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)
Although openssl returns that 19 error, it no longer is an issue for Java HttpsURLConnection
and that is all I care about.
So, how can I export the whole chain from JKS in a format (e.g. PEM) which works with both nginx server and Java client? What am I missing?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我经常遇到的一个相当大的问题是,当生成 CSR 来获取我们的证书时,密钥库(Sun 格式的 jks 密钥库)不会输出 .key 或提供任何获取 .key 的工具。因此,我总是得到一个 .pem/.crt,但无法将其与 Apache2 一起使用,Apache2 无法像 Tomcat 那样读取 JKS 密钥库,而是需要未打包的 .key + .pem/.crt 对。
首先,获取现有密钥库的“副本”并跳到下面的第 5 个命令,或者像这样创建自己的命令:
然后,可以选择创建 2 年 CSR,然后在接下来的 3 个步骤过程中导入 CSR 响应:
要使其正常工作,并且如果您已经拥有用于 Tomcat 应用程序服务器的 JKS 密钥库文件,请按照以下步骤操作:
首先,将 DER(二进制)格式的证书获取到名为“exported-der.crt”的文件中:
然后,查看&验证它:
现在您需要将其转换为 PEM 格式,该格式在 Apache 等应用程序中更广泛使用,并由 OpenSSL 进行 PKCS12 转换:
私钥:
然后,下载并使用 ExportPriv 从密钥库中获取未加密的 现在您可能意识到,私钥正在导出为 PKCS#8 PEM 格式。要将其转换为适用于 Apache 的 RSA 格式(PKCS#12??),您可以发出以下命令:
A rather large problem that I frequently encounter is that, when generating the CSR to get our certificate, the keystore (Sun formatted jks keystore) does not output the .key or provide any facility for obtaining the .key. So I always had ended up with a .pem/.crt with no way of using it with Apache2, which cannot read a JKS keystore like Tomcat can, but instead requires a unpackaged .key + .pem/.crt pair.
To start, get a “copy” of your existing keystore and skip to the 5th command below, or create your own like this:
Then, optionally, create a 2-year CSR and then import the CSR response, in the next 3 step process:
To get this working, and if you already have your JKS keystore file that you use for a Tomcat application server, follow the following steps:
First, get the DER (binary) formatted certificate into a file called “exported-der.crt”:
Then, view & verify it:
Now you will want to convert it to PEM format, which is more widely used in applications such as Apache and by OpenSSL to do the PKCS12 conversion:
Then, download and use ExportPriv to get the unencrypted private key from your keystore:
By now you probably realize, the private key is being exported as PKCS#8 PEM format. To get it into the RSA format that works with Apache (PKCS#12??) you can issue the following command:
我不确定是否可以使用 keytool 提取链,但可以使用一个小型 Java 程序来完成:
此代码应在提交的目录中以 DER 格式写入链的所有证书。
I'm not sure it is possible to extract the chain with
keytool
but it can be done with a small Java program:This code should write all certificates of the chain in DER format in the submitted directory.
您可以轻松地将 JKS 文件转换为 PKCS12 文件:
然后您可以使用以下命令提取私钥和任何证书:
You can easily convert a JKS file into a PKCS12 file:
You can then extract the private key and any certs with: