获取包含根证书的完整证书链

获取包含根证书的完整证书链

问题描述:

如何获得服务器的完整证书链?尽管有些索赔one should be able to do just thatopenssl s_client -showcerts,但情况并非总是如此。获取包含根证书的完整证书链

echo | openssl s_client -CApath /etc/ssl/certs -connect www.ssllabs.com:443 \ 
         -showcerts | grep -B2 BEGIN 
depth=3 C = SE, O = AddTrust AB, OU = AddTrust External TTP Network, CN = AddTrust External CA Root 
verify return:1 
depth=2 C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO RSA Certification Authority 
verify return:1 
depth=1 C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO RSA Domain Validation Secure Server CA 
verify return:1 
depth=0 OU = Domain Control Validated, OU = PositiveSSL, CN = www.ssllabs.com 
verify return:1 
0 s:/OU=Domain Control Validated/OU=PositiveSSL/CN=www.ssllabs.com 
    i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA 
-----BEGIN CERTIFICATE----- 
-- 
1 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA 
    i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority 
-----BEGIN CERTIFICATE----- 
-- 
2 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority 
    i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root 
-----BEGIN CERTIFICATE----- 
DONE 

这里我们有三个证书我们四个。所有除AddTrust External CA Root证书。 (可能是因为它没有包含在证书包中,不需要这样做,是的,我可以在/etc/ssl/certs找到丢失的文件)

如何以全自动方式获取服务器的所有证书?

你拿到链包括verify_callback(见SSL_CTX_set_verify里面内置的受信任的根证书在一个小的Perl程序,你可以转储链是这样的:

#!/usr/bin/perl 
use strict; 
use warnings; 
use IO::Socket::SSL; 

IO::Socket::SSL->new(
    PeerHost => 'www.google.com:443', 
    SSL_verify_callback => sub { 
     my $cert = $_[4]; 
     my $subject = Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_subject_name($cert)); 
     my $issuer = Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_issuer_name($cert)); 
     print "# $subject (issuer=$issuer)\n"; 
     print Net::SSLeay::PEM_get_string_X509($cert),"\n"; 
     return 1; 
    } 
) or die $SSL_ERROR||$!; 

Meta:我试图以超级用户的方式回答这个问题,但是你删除了它。幸运的是,当我发现这份副本时,我的大部分工作仍然坐在笔记本上,我没有关闭,否则我不会愿意做两次研究工作。

s_client -showcerts显示由服务器发送的证书;根据RFC,这个应该是以上行顺序的有效链,除了,根MAY(在RFC2119定义中,即允许但不是特别推荐的)被省略。但是,并非所有服务器都配置正确,有些可能会发送额外的,缺少的和/或无序的证书。也取决于使用的CA可能有多个有效的链,但服务器只能发送一个。 openssl目前将只使用链接发送,但这将在1.0.2中很快发生变化,其他反馈者有时会发现与发送链不同的链。

的OpenSSL:如果接收到的链是完成多达和也许包括根部,其是在使用的信任(其默认位置取决于系统或建立,并且在任何情况下,总是可以被重写),然后OpenSSL的客户端会验证它是否可用 - 除非它已过期,或者被撤销,并且通常不可用的信息。在这种情况下,您可以编写一个客户端程序,该程序在设置cert-verify回调函数之后进行连接,该函数输出由验证循环处理的完整证书或其他信息,而不是s_client,该函数使用回调函数只记录depth=n行中的主题名称,您可以在示例中看到这些主题名称,其中包含链中的所有4个证书。 openssl是开源的,因此一个客户端程序主要用于s_client,可以是s_client的修改副本(在本例中为s_cb.c)。

Java也可以做到这一点,并且编写起来比较简单,但需要安装Java。如果接收到的链在中使用的信任库(缺省为一组公共根,但可以修改或重写,并且可以具有非根锚),那么您同样可以编写一个程序(可能是20行)使用HandshakeCompletedListener进行连接,其中转储来自event.getPeerCertificates()的信息。但是,如果链不验证,Java将中止握手并产生异常,并且根本不会获得任何证书,这与openssl案例中的错误发生前可能获得部分信息不同 - 至少默认情况下,openssl的检查isn无论如何,这并不是很严格。

更新:为了完整起见,在Java 7+中,命令行keytool -printcert -sslserver显示以相当混乱的格式发送的链。

其中浏览器我可以很容易地检查,Windows上的Firefox和Chrome(至少)可以写出他们找到并验证的链。 ISTR,但不能轻易地重新测试Firefox错误/异常对话框,也可以对无法验证并可能不完整的链执行此操作。这些不是自动的,但我已经看到许多“模拟GUI用户输入”工具的广告,显然可以根据需要驱动它们。