Tomcat中间证书`sec_error_unknown_issuer'

时间:2012-08-19 15:34:25

标签: java tomcat ssl x509 keytool

我有一个测试场景,一个名为 Root 的根证书颁发机构签署一个由名为 Intermediate 的中间证书颁发机构创建的证书签名请求,后者又签署证书由名为主题的主题创建的签名请求。

我使用Tomcat作为我的Web服务器,并且我已将其配置为使用 Subject 密钥存储区(其中包含 Root 证书, Intermediate 证书,主题证书链和主题私钥),我启动它来侦听端口80(HTTP)和443(HTTPS)。

我在Firefox中安装了 Root 证书(作为可信证书),我点击了我的域名,这就是我得到的:

subject.usip.me uses an invalid security certificate.
The certificate is not trusted because no issuer chain was provided.
(Error code: sec_error_unknown_issuer)

显然,Firefox无法验证链的信任或类似的东西。现在,在我详细介绍我的配置和我采取的步骤之前:我已经更改了我的Tomcat配置,以便它使用 Intermediate 密钥存储而不是使用 Subject 密钥库(中间密钥库包含证书,中间证书链和中间私钥)。使用此配置一切正常。

我使用以下工具:

  • Java:1.7.0_05
  • Tomcat:7.0.29
  • Firefox:14.0.1

I create the key stores in question with the following script pasted over here(这很长)。任何拥有Java keytool 的人都可以运行它(由于4096 RSA密钥大小,它可能不会太快运行。)

脚本运行后,我可以验证我的主题密钥库是否包含完整的信任链(正如我所看到的):

c:\>keytool -list -keystore c:\subject.jks -storepass changeit -rfc

It prints out the following (again, quite lengthy) output which is pasted over here。对我来说似乎没问题(至少,经过数小时的挣扎,我似乎无法开始看到它出现任何问题)。

我通过它的 server.xml 设置了Tomcat(following this how-to)(除了这个单独的标签,我没有更改,默认情况下是注释掉的)。

<Connector port="443" protocol="HTTP/1.1" SSLEnabled="true"
           maxThreads="150" scheme="https" secure="true"
           clientAuth="false" sslProtocol="TLS"
           keystoreFile="c:/subject.jks"
           keystorePass="changeit"
           keystoreType="jks"
           keyAlias="subject"
           keyPass="changeit" />

(启动Tomcat后,连接到它 - 当它使用 Subject Intermediate 密钥存储区时 - 没有记录错误。)

在寻找解决方案时,我发现使用 openssl 我可以验证我的服务,作为该工具的新手用户,我对我的域运行了以下命令(使用Cygwin):

$ openssl s_client -connect subject.usip.me:443 -CAfile /cygdrive/c/root.pem -showcerts &> /cygdrive/c/openssl.log

然而,I've pasted the lengthy output over here

它表示Verify return code: 24 (invalid CA certificate),这是奇怪的,因为它(如我所见)指向 Root 证书。现在,当我说我重新配置Tomcat之前使用 Intermediate 密钥存储区时,我也运行了同样的命令,然后用Verify return code: 0 (ok)检出。所以我访客 Root 证书没问题。

我通过帖子和贴片提到的域名和子域名是http://freedns.afraid.org/注册的免费域名,每个域名都指向我当前的地址(我以为我会提到它,也许这很重要)。

任何想法我做错了什么?

1 个答案:

答案 0 :(得分:1)

好的,我已经成功解决了这个问题。当我生成对证书签名请求的回复时,我没有指定一些重要的X.509证书扩展。

There is some info on this in Java's keytool documentation。 (搜索-ext。)

关键点是正确生成中级证书的签名

keytool -gencert^
 -alias root^
 -ext BasicConstraints:critical=ca:true,pathlen:0^
 -ext KeyUsage:critical=keyCertSign,cRLSign^
 -infile intermediate.csr^
 -keypass changeit^
 -keystore root.jks^
 -outfile intermediate.pem^
 -rfc^
 -sigalg sha512withrsa^
 -storepass changeit^
 -storetype jks^
 -v

主题证书

keytool -gencert^
 -alias intermediate^
 -ext BasicConstraints:critical=ca:false^
 -ext ExtendedkeyUsage:critical=serverAuth,clientAuth^
 -ext KeyUsage:critical=digitalSignature,keyEncipherment^
 -infile subject.csr^
 -keypass changeit^
 -keystore intermediate.jks^
 -outfile subject.pem^
 -rfc^
 -sigalg sha512withrsa^
 -storepass changeit^
 -storetype jks^
 -v

当我有时间并发布完整的解决方案时,我会更新我的答案。

更新

I've set up a little example repository at GitHub,其中包含我为生成必要的密钥库文件,证书等而编写的脚本。我在Bash中重写了脚本,并为其添加了许多配置参数。它可以在没有任何配置的情况下运行。在这种情况下,它将为 root.lvh.me intermediate.lvh.me subject.lvh.me 域创建证书( the second level, lvh.me domain points to 127.0.0.1 by default)。将 Subject 密钥库与Tomcat一起使用并将 Root 证书安装到Firefox中将导致与 https://subject.lvh.me <的验证,安全连接/ em>(以及其他任何地方,因此 https://intermediate.lvh.me 将无法验证)。