如何使用中间和根CA证书链接SSL服务器证书?

时间:2015-04-03 17:29:30

标签: ssl openssl ssl-certificate x509

我以为我明白了,但它没有用!

我和其他人一起阅读http://binblog.info/2010/02/02/lengthy-chains/,这是我找到的最清晰的解释。

背景: Comodo便宜的PositiveSSL服务器证书带有一个root和两个中间CA证书(我用myserver.com替换了我的FQDN):

$ unzip ../myserver_com.commodo.certificate.zip 
Archive:  ../myserver_com.commodo.certificate.zip
 extracting: AddTrustExternalCARoot.crt  
 extracting: COMODORSAAddTrustCA.crt  
 extracting: COMODORSADomainValidationSecureServerCA.crt  
 extracting: myserver_com.crt           

请注意,字母顺序类似于从根CA到服务器证书的反向证书链。根CA不是Comodo,但这不是重点。

考虑以下输出:

openssl x509 -noout -subject -issuer -in myserver_com.crt 
subject= /OU=Domain Control Validated/OU=PositiveSSL/CN=myserver.com
issuer= /C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA

openssl x509 -noout -subject -issuer -in COMODORSADomainValidationSecureServerCA.crt 
subject= /C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
issuer= /C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority

openssl x509 -noout -subject -issuer -in COMODORSAAddTrustCA.crt 
subject= /C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
issuer= /C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root

openssl x509 -noout -subject -issuer -in AddTrustExternalCARoot.crt 
subject= /C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
issuer= /C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root

前证书的颁发者是后者的主题 - 直到来自AddTrust AB的根CA证书是自签名的。链条完整。

验证单个证书可以:

$ openssl verify *.crt
AddTrustExternalCARoot.crt: OK
COMODORSAAddTrustCA.crt: OK
COMODORSADomainValidationSecureServerCA.crt: C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO RSA Domain Validation Secure Server CA
error 20 at 0 depth lookup:unable to get local issuer certificate
myserver_com.crt: OU = Domain Control Validated, OU = PositiveSSL, CN = myserver.com
error 20 at 0 depth lookup:unable to get local issuer certificate

服务器上已经安装了前两个证书,这两个证书会连接两个证书,但无论如何我都将它们链接起来。

来自RFC5246 http://tools.ietf.org/html/rfc5246#section-7.4.2

 certificate_list

 This is a sequence (chain) of certificates.  The sender's
 certificate MUST come first in the list.  Each following
 certificate MUST directly certify the one preceding it.  Because
 certificate validation requires that root keys be distributed
 independently, the self-signed certificate that specifies the root
 certificate authority MAY be omitted from the chain, under the
 assumption that the remote end must already possess it in order to
 validate it in any case.

当我以正确的方式链接时,证书被识别为TLS会话的服务器证书,但未经过验证。

$ cat myserver_com.crt COMODORSADomainValidationSecureServerCA.crt COMODORSAAddTrustCA.crt AddTrustExternalCARoot.crt > chained.crt
$ openssl verify chained.crt 
chained.crt: OU = Domain Control Validated, OU = PositiveSSL, CN = das.email
error 20 at 0 depth lookup:unable to get local issuer certificate

使用

连接服务器时
$ openssl s_client -crlf -connect myserver:465

证书被接受并且链被识别,但根证书未被识别为可信任,尽管它存在于/ etc / ssl / mozilla /中的受信任证书中。

我错过了什么?我可以简单地忽略命令行openssl工具中的错误吗?

1 个答案:

答案 0 :(得分:1)

openssl verify chained.crt没有(直接)验证您认为的链条;它从文件中读取一个(第一个)证书,并根据信任库对其进行验证。这里的第一个证书是您的服务器(叶)证书,它由您的第一个中间件(Comodo DV服务器)发出,它不在信任库中,因此查找失败。要做(几乎)由协议中收到的链的SSL客户端完成的验证,请执行:

openssl verify -purpose sslclient -untrusted restofchain myserver.crt 

其中restofchain是一个至少包含链中其他证书的文件 除了可以省略根,所以在你的情况下是 两个Comodo中间证书和可选的AddTrust根证书。 openssl并不要求它们按5246的顺序排列, 但如果他们这样的话就没问题。事实上,如果叶证书存在 在文件中,它将被忽略,因此您只需使用chained.crt

对于s_client我不确定你的意思是“证书被接受......但根证书不被识别为可信任”。如果s_client调用的libssl-client代码成功验证了收到的链,那么用于该链的根必须位于本地信任库中,因为这是openssl认为验证成功的唯一情况 - 至少通过1.0.1,即使在最近的1.0.2中它仍然是默认值 - 但它从不输出“可信任”这个词。

一个可能的混淆源:与真实客户端(如浏览器或Java程序)不同,如果收到的证书/链未验证,或者至少需要手动覆盖以继续,则会中止连接,s_client是无论证书状态如何,始终进行连接的测试工具。您必须专门查看验证错误(靠近输出顶部)和/或“验证返回代码”(通常位于最底部)。

编辑4/21:OpenSSL到1.0.2a至少有一个bug; s_client(以及s_servers_time实际上并未使用默认信任库,如果您未指定-CAfile-CApath参数。见https://serverfault.com/questions/607233/how-to-make-openssl-s-client-using-default-ca;为dev发布了一个修复程序,但是除非你自己做了自己的构建,直到它被释放和分发,你需要明确指定-CA*参数,即使它看起来是多余的。