Tomcat HTTPS密钥库证书

18
遇到了使用SSL和Tomcat的另一个问题:我已经配置了一个包含密钥和证书的密钥库(我希望向连接到站点的客户端呈现服务器证书)。我对信任库进行了相同的配置(我将需要客户端身份验证)。
现在我的问题是,当我通过HTTPS连接到我的Tomcat实例时,呈现给我的证书(服务器证书)不是我的实际服务器证书,而是JKS密钥库中的“key”(密钥)。使用-Djavax.net.debug = ssl会显示它为客户端身份验证提供了正确的CA,但未提供正确的服务器证书。
添加为受信任的证书:
  主题: CN=A
  颁发者: CN=A
  算法: RSA; 序列号: -
  有效期从Tue Nov 10 14:48:31 CET 2009至Mon Feb 08 14:48:31 CET 2010
添加为受信任的证书: 主题: X 颁发者: X 算法: RSA; 序列号: - 有效期从Wed Jan 19 01:00:00 CET 2005至Mon Jan 19 00:59:59 CET 2015
我用占位符替换了真实值。A = 服务器的域名(但在这种情况下,由于某种原因,这是密钥而不是证书)。X = VeriSign CA(应该是正确的)。我有一个现有的证书,希望将其导入到JKS密钥库中以呈现给客户端。
Tomcat连接器配置:
<Connector port="444" protocol="HTTP/1.1" SSLEnabled="true"
  maxThreads="150" scheme="https" secure="true"
  clientAuth="false" sslProtocol="TLS"     
  keystoreFile="conf/ssl/keystore.jks"
  keystorePass="xx"
  keyAlias="testkey"
  truststoreFile="conf/ssl/truststore.jks"
  truststorePass="xx" />

我的Tomcat实例为什么没有显示正确的证书?


给出 SSL 连接器配置(来自 server.xml)。 - Bozho
4个回答

15

问题是(显然——我无法确认这一点),无法将先前生成的证书(及其匹配的密钥)正确导入到JKS密钥库中,并且Tomcat无法正确地呈现它。

我的问题出现的情况如下:

  1. 我有一个证书文件,我使用OpenSSL从头开始生成了自己的密钥和CSR -> 证书签名,由我自己的CA签名。
  2. 我希望配置Tomcat,以便向连接到我的站点的用户呈现特定的证书

我发现可行的解决方案是:

  1. 将现有证书及其私钥转换为DER格式。例如(使用OpenSSL):

    对于私钥

    openssl pkcs8 -topk8 -nocrypt -in my_private_key.key -inform PEM -out my_private_key.der -outform DER

    对于实际的签名证书

    openssl x509 -in my_certificate.crt -inform PEM -out my_certificate.der -outform DER

  2. 使用自定义Java类将两个DER文件导入到密钥库(JKS文件)中。

    java ImportKey my_private_key.der my_certificate.der

    我没有自己想出来(所有荣誉归原发明人所有)。可以在此处此处找到此Java类的源代码和更多详细信息。我稍微修改了这个类,以便有第三个(或第四个)参数指定生成的JKS文件的输出位置。

最终的结果是生成一个JKS密钥库文件,并可以在Tomcat连接器配置中作为密钥库使用。上述工具将使用默认密码生成JKS文件和密钥的密码,这些密码可以稍后通过keytool -storepasswdkeytool -keypasswd命令进行更改。希望对面临相同问题的人有所帮助。


2
+1. 第二个链接(agentbob.info)对我有效。它向密钥库发出密码,而第一个链接(comu.de)没有。Java的keytool不喜欢更改没有密码的密钥库的密码。此外,您可以指定tomcat期望的关键别名(它是“tomcat”)。 - Wolfgang
旧的 keytool -import,自 IIRC j5 ~2005 正式更名为 -importcert,无法导入私钥。您可以使用 openssl pkcs12 -export 将 PEM 私钥和匹配证书(以及可选且最好的任何所需 chain 证书)组合成 PKCS12,Java 本身可以读取但某些程序无法使用,在这种情况下,您可以使用 keytool -importkeystore -srcstoretype pkcs12 -deststoretype jks ... 转换为 JKS。(自 2015 年的 8u60 以来,几乎所有程序都接受 PKCS12。) - dave_thompson_085
然而,Tomcat >= 8.5(很快将成为唯一支持的版本)不再需要密钥库,它使用一种新的配置方案,即使对于JSSE也可以使用OpenSSL源PEM文件,因此这将很快过时。 - dave_thompson_085

3

您的配置应该可以正常工作。

Tomcat的使用指南解释了如何采取步骤来拥有一个正确的JKS。

请确保您已经将证书导入到JKS中,并使用适当的别名(testKey)。


当我将keyAlias设置为密钥库中证书的别名时,Tomcat将无法正确启动。我认为keyAlias参数用于指定密钥,而不是证书。我有一种感觉,因为证书是单独创建的,所以Tomcat永远不会正确地呈现我的证书。现在我打算尝试使用keytool从头开始生成全新的证书,而不是使用openssl,看看是否会有所不同。 - tmbrggmn
1
是的,请尝试一下。正如在Tomcat how-to中所示,密钥和证书必须在同一个别名下。 - Bozho
我已经完成了这个任务,使用keytool生成了密钥和CSR,使用OpenSSL用自己的CA签名,并将签名证书导入回密钥库。但是,出于某种原因,Tomcat仍然发送keyEntry而不是trustedCertificate entry。 - tmbrggmn
它可能是因为签名证书的CA不在信任库中,所以无法呈现证书吗? - tmbrggmn
我已经想通了 - 等我有空的时候,我会很快回答我的问题(我已经在这上面浪费了太多时间:D)。 - tmbrggmn
显示剩余3条评论

2

在@Bozho的评论上进一步扩展,

这非常关键。“关键是密钥和购买的证书必须使用相同的别名”。

从CA(Verisign、Digicert等)购买的SSL证书应该使用与创建csr之前生成的私钥相同的别名导入。使用Java keytool将已购买的证书导入密钥库后,您将看到“证书回复已添加到密钥库”。

要检查信任链,请使用终端命令openssl s_client -connect yourdomain.com:443 -showcerts。它从您的证书开始,一直延伸到受信任的根CA。


0

以下是生成密钥库中正确证书条目的命令。背景知识:自Tomcat 7版本以来,Tomcat支持PKCS12作为密钥库格式,并且Java密钥库可以轻松导入此类文件。更多背景知识:密钥库中的密钥条目需要完整的证书链存在,否则将会发生SSL错误。

所以这里是要做的事情:

  1. 将您的中间(签名根)证书和根CA证书连接在一起:

    cat intermediate.pem root.pem > chain.pem

  2. 将已签名的证书与链连接在一起:

    cat cert.pem chain.pem > fullchain.pem

  3. 现在,使用完整的链和清晰标识的根创建一个pkcs12文件。确保在执行此命令时,将您使用CSR生成的私钥(在我的示例中命名为privkey.pem)复制到与其他生成的文件相同的目录中:

    openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out keystore.p12 -name server -CAfile chain.pem -caname root

  4. 好的,很酷;这个文件应该可以正常工作。您可以将其直接复制到conf/ssl并修改server.xml以使用keystore.p12而不是keystore.jks。或者,您可以通过cd到conf/ssl并运行以下命令将其导入到keystore文件中(可能要先备份):

    keytool -importkeystore -destkeystore keystore.jks -deststoretype JKS -srckeystore keystore.p12 -srcstoretype PKCS12 -alias server


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接