tomcat 不提供中间证书(https)
Posted
技术标签:
【中文标题】tomcat 不提供中间证书(https)【英文标题】:tomcat doesn't deliver intermediate certificate (https) 【发布时间】:2011-12-28 13:45:27 【问题描述】:我使用 openssl 可执行文件在控制台上创建了一个密钥和一个 csr。 然后我将 csr 发送到 CA 并取回证书。现在我想把它导入到tomcat中。
所以我用我的密钥和证书创建了一个 PKCS#12 文件:
openssl pkcs12 -export -in mycert.cert -inkey mykey.pem -out key_and_cert.p12
然后创建一个包含它的密钥库:
keytool -importkeystore -deststorepass [password] -destkeystore keystore.jks -srckeystore key_and_cert.p12 -srcstoretype PKCS12 -srcstorepass [password]
然后我导入中间证书chain.crt:
keytool -import -trustcacerts -alias root -file chain.crt -keystore keystore.jks
这里是“keytool -keystore keystore.jks -list”的输出:
Keystore-Typ: JKS
Keystore-Provider: SUN
Ihr Keystore enthält 2 Einträge.
root, 14.11.2011, trustedCertEntry,
Zertifikatsfingerabdruck (MD5): [fingerprint]
1, 14.11.2011, PrivateKeyEntry,
Zertifikatsfingerabdruck (MD5): [fingerprint]
tomcat server.xml 包含:
<Connector port="443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" URIEncoding="UTF-8" compression="on"
sslProtocol="TLS"
keystoreFile="/[absolute-path]/keystore.jks"
keystorePass="[password]" />
当我重新启动 tomcat 时,它在 catalina.out 中没有记录任何错误,一切似乎都很好。 但是当我运行Firefox时,它会报告
[domain] uses an invalid security certificate.
The certificate is not trusted because no issuer chain was provided.
(Error code: sec_error_unknown_issuer)
运行“openssl s_client -connect [domain]:443 -showcerts”返回
CONNECTED(00000003)
depth=0 C = DE, OU = Domain Control Validated, CN = [domain]
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 C = DE, OU = Domain Control Validated, CN = [domain]
verify error:num=27:certificate not trusted
verify return:1
depth=0 C = DE, OU = Domain Control Validated, CN = [domain]
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
0 s:/C=DE/OU=Domain Control Validated/CN=[domain]
i:/C=BE/O=GlobalSign nv-sa/CN=GlobalSign Domain Validation CA - G2
-----BEGIN CERTIFICATE-----
[certificate from mycert.cert]
-----END CERTIFICATE-----
---
Server certificate
subject=/C=DE/OU=Domain Control Validated/CN=[domain]
issuer=/C=BE/O=GlobalSign nv-sa/CN=GlobalSign Domain Validation CA - G2
---
No client certificate CA names sent
---
SSL handshake has read 1777 bytes and written 289 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : SSLv3
Cipher : ECDHE-RSA-AES256-SHA
Session-ID: [session-id]
Session-ID-ctx:
Master-Key: [master-key]
Key-Arg : None
PSK identity: None
PSK identity hint: None
Start Time: 1321268519
Timeout : 7200 (sec)
Verify return code: 21 (unable to verify the first certificate)
---
我认为虽然tomcat知道中间证书,但它不会提供中间证书。怎么做才能让tomcat投递呢?
附加信息: 导入 pkcs12 证书时,没有证书链错误,因为 -importkeystore 命令不检查链。我也试过先导入中间证书,然后调用-importkeystore。我得到了同样的结果。
编辑: 我刚刚尝试了另一种方式,将链直接插入到 PKCS#12 证书中,并得到以下错误:
$ openssl pkcs12 -export -CAfile chain.pem -in mycert.cert -inkey mykey.pem -out key_and_cert.p12 -name tomcat -chain
Error unable to get issuer certificate getting chain.
但是链证还可以:
$ openssl verify chain.pem
chain.pem: OK
【问题讨论】:
你的链 PEM 中有根 CA 吗? 什么给了你“openssl verify -CAfile chain.pem mycert.cert”? 【参考方案1】:我必须通过为我的颁发者找到根证书然后将中间证书放在同一个文件中来创建一个 CA 文件。然后我跑了:
openssl pkcs12 -export -chain -inkey mykey.key -in mye.crt -name "tomcat" -CAfile intermediate_plus_root.crt -out key_and_cert.p12【讨论】:
我用了这个方法但是报错:“Error cannot get issuer certificate getting chain.”所以我按照我在网上找到的一些建议做了:cat PrimaryCA.pem /etc/ssl/certs/ca-certificates.crt SecondaryCA.pem > intermediate_plus_root.crt。重新运行上述并解决了问题。【参考方案2】:在某些 cmets 中甚至有一个更简单的解决方案(无需在 /etc/ssl/certs 中保存根证书和中间证书)
首先将所有需要的根证书和中间证书复制到一个文件夹中(在我们的示例中,文件夹是“~/certs”,我们的两个证书分别命名为“PrimaryCA.pem”和“SecondaryCA.pem”):
mkdir ~/certs
mv PrimaryCA.pem ~/certs/PrimaryCA.pem
mv SecondaryCA.pem ~/certs/SecondaryCA.pem
然后 'c_rehash' 文件夹:
c_rehash ~/certs
现在 certs 文件夹将包含两个新符号链接,这些符号链接的名称与以下方案“hash-value.n”有关,其中 hash-value 是一个 8 符号哈希值,n 是一个整数。如果您是这种情况,请继续执行以下命令,该命令使用“-CApath”创建您的 .p12,而不是将证书复制到 /etc/ssl/certs:
openssl pkcs12 -export -in cert.pem -inkey key.key -out key_and_cert.p12 -chain -CApath ~/certs
最后将其转换为 jks 为 Heinzi 在他的回答中已经完美描述:
keytool -importkeystore -deststorepass [password] -destkeystore keystore.jks -srckeystore key_and_cert.p12 -srcstoretype PKCS12 -srcstorepass [password]
【讨论】:
我想补充一点,您需要将 P12 文件中的证书重命名为“tomcat”。我在里面有一个名字'1'。我为此使用了keystore-explorer.org/downloads.html。 从另一边你可以指定为openssl的参数:openssl pkcs12 -export -name "tomcat" -in cert.pem -inkey key.key -out key_and_cert.p12 -chain -CApath ~/certs
【参考方案3】:
我终于让它工作了。这不是一个干净的解决方案,但它有效。我将中间证书添加到我的本地 /etc/ssl/certs 然后调用
openssl pkcs12 -export -in cert.pem -inkey key.key -out key_and_cert.p12 -chain
生成的 pkcs12 证书我通过以下方式转换为 jks
keytool -importkeystore -deststorepass [password] -destkeystore keystore.jks -srckeystore key_and_cert.p12 -srcstoretype PKCS12 -srcstorepass [password]
这个生成的文件现在似乎可以工作了,tomcat 也将证书链传递给在 /etc/ssl/certs 目录中没有中间证书的客户端。 但我认为也必须有一种不改变 /etc/ssl/certs 的方法。
【讨论】:
你会碰巧找到一个更干净的解决方案吗?我有一个非常相似的问题。 很遗憾没有,但您可以在之后从 /etc/ssl/certs 中删除证书 请注意,您可以将 PKCS#12 (.p12) 文件直接用作 Java 中的密钥库:使用PKCS12
存储类型(在您的 Apache Tomcat 连接器配置中使用 keystoreType="PKCS12"
)。跨度>
请注意,openssl 命令应在出现提示时或使用 -passout 参数提供导出密码,因为以下 keytool 命令不适用于空白 srcstorepass。
发现需要在pkcs12 -export
命令中添加-certfile [intermediate cert]
。这样,我就获得了自己的证书以及某些客户所需的中间证书。【参考方案4】:
它适用于我使用 APR。见http://tomcat.apache.org/tomcat-7.0-doc/config/http.html#SSL_Support_-_APR/Native
<Connector port="3573" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
SSLCertificateFile="/my/pem/encoded/certificate/file"
SSLCertificateKeyFile="/my/pem/encoded/certificate/private_key"
SSLPassword="yourKeyFilePassword"
SSLCertificateChainFile="/my/pem/encoded/certificate/authorities/file"
/>
【讨论】:
【参考方案5】:确保将 openssl ca 文件复制到中间文件中。
在 RHEL 上将以下文件连接到您的颁发者 ca 文件。
/etc/pki/tls/certs/ca-bundle.crt
【讨论】:
以上是关于tomcat 不提供中间证书(https)的主要内容,如果未能解决你的问题,请参考以下文章