SSL证书链捆绑是如何工作的?

60

我已经创建了这样的链层次结构。

root-ca ==> signing-ca ==> subordinate-ca ==> server

提到创建链束时,最低的应该首先放置。

$ cat server.crt subordinate-ca.crt signing-ca.crt > server.pem

但是验证失败了。

$ openssl verify -CAfile root-ca.crt server.pem
error 20 at 0 depth lookup:unable to get local issuer certificate

然而,如果我改变顺序,它似乎能够工作。

$ cat signing-ca.crt subordinate-ca.crt server.crt > server.pem
$ openssl verify -CAfile root-ca.crt server.pem
server.pem: OK

那么这里会有什么错误?

“cat”之后的链看起来像下面这样。

-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

更多信息:根据"http://www.herongyang.com/crypto/openssl_verify_2.html"的说法,我执行了以下测试,它有效。


$ cat signing-ca.crt subordinate-ca.crt > inter.crt
$ openssl verify -CAfile root-ca.crt -untrusted inter.crt server.crt
server.crt: OK

那是否意味着所有链接都是好的?

好的,我最终发现这无法通过OpenSSL命令行完成(或者至少不容易)。http://openssl.6102.n7.nabble.com/check-certificate-chain-in-a-pem-file-td43871.html


很难确定,但你的证书链似乎确实出了问题。据我所知,第一种情况下的openssl verify将检查证书链并失败,而第二种情况下只会检查从signing-ca.crt到根证书的链(不需要其他证书,因此只是忽略它们)。 - Joachim Isaksson
@JoachimIsaksson,好的,明白了。如何逐级调试?如果我执行“openssl verify -CAfile subordinate-ca.crt server.crt”,它应该是失败还是成功? - user180574
据我所知,如果服务器证书是下级CA证书的直接“子级”,则应该成功。 - Joachim Isaksson
@JoachimIsaksson,这是不正确的,验证链的一部分而不包括根会失败。请检查我在问题中添加的链接。但还是谢谢你,你的评论很有用。 - user180574
请确保在连接文件之前,首先使用dos2unix对其进行处理,以消除LF结尾的问题。这是我遇到过并表现为“140017985005208:error:0906D066:PEM routines:PEM_read_bio:bad end line:pem_lib.c:809:”样式错误的情况。 - David Thornley
2个回答

30

10
用于 Nginx 的证书捆绑包需要将证书的顺序颠倒,首先是同行证书,然后是以根 CA 结尾的链。保持一致性肯定是好的!http://nginx.org/en/docs/http/configuring_https_servers.html - David Vezzani
实际上,我相信我在这里的回答是错误的,你是正确的;当时我的理解是有缺陷的。 - Vynce
7
Nginx和标准相互匹配。RFC规定:“发送方的证书必须在列表中首先出现。”nginx说:“服务器证书必须在合并文件中的链式证书之前出现。” - mikemaccana
看起来好像是相反的,但实际上,这是按照处理顺序进行的。为了检查一个签名,你首先必须有要检查的对象,而且这个对象还必须持有签名。这个对象就是叶子。 - undefined

9

当前最佳答案在多个方面都是错误的。

首先,它忽略了主要问题,即“验证”不能以这种方式验证单个文件中的证书链。证据:

$ cp /etc/ssl/certs/Certigna_Root_CA.pem /tmp/poc.pem
$ echo "unverifiable garbage" >> /tmp/poc.pem
$ openssl verify /tmp/poc.pem 
/tmp/poc.pem: OK

因此,在原始问题中提供的2个排序中,只有一个在开头具有根证书的排序将报告“OK”,因为该调用仅检查根证书,并且已被系统信任。
关于证书排序,标准中指定的顺序(“发送方的证书必须排在列表的第一位。”)和nginx的顺序(“服务器证书必须出现在组合文件中链接的证书之前”)匹配。这对应于OP使用cat进行的第一次尝试。
实际上正确的答案在OP链接的电子邮件线程中。我在此引用它:

on the command line, things are unnecessarily difficult.

Here is what you need to do:

  1. Split the chain file into one file per certificate, noting the order

  2. For each certificate starting with the one above root:

2.1 Concatenate all the previous certificates and the root certificate to one temporary file (This example is for when you are checking the third certifate from the bottom, having already checked cert1.pem and cert2.pem

Unix:    cat cert2.pem cert1.pem root.pem > cert2-chain.pem
Windows: copy /A cert1.pem+cert1.pem+root.pem cert2-chain.pem /A

2.2 Run this command

         openssl verify -CAfile cert2-chain.pem cert3.pem

2.3 If this is OK, proceed to the next one (cert4.pem in this case)

Thus for the first round through the commands would be

Unix: cat root.pem > root-chain.pem Windows: copy /A root.pem root-chain.pem Both: openssl verify -CAfile root-chain.pem cert1.pem

And the second round would be

Unix: cat cert1.pem root.pem > cert1-chain.pem Windows: copy /A cert1.pem+root.pem cert1-chain.pem Both: openssl verify -CAfile cert1-chain.pem cert2.pem

Etc.

进一步说明:

  1. 第一步(分割文件)可以通过以下方式自动化:
csplit -f cert- $file '/-----BEGIN CERTIFICATE-----/' '{*}'
  1. openssl verify 获取系统中关于信任的信息(例如 /etc/ssl/certs/),因此如果您确实想要确保正确验证,您的调用应该类似于 openssl verify -verbose -x509_strict -CAfile upto-cert-02 -CAPath nosuchdir cert-01(其中nosuchdir是一个不存在的路径,“upto-cert-02”是文件cert-nn到certt02的串联)

-CApath nosuchdir 给出错误:“verify: Not a directory: nosuchdir”。nosuchdir 应该是一个现有的目录才能正常工作。 - drrossum
你会收到“不是目录”错误,是因为较新版本的openssl会验证参数,而较旧版本则不会。然而,较新版本还包括一个更好的选择,即-no-CApath选项。 - undefined

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