【问题标题】:Get complete certificate chain including the root certificate获取完整的证书链,包括根证书
【发布时间】:2014-12-02 08:18:22
【问题描述】:

如何获得服务器的完整证书链?虽然有些人声称 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 找到丢失的那个)

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

【问题讨论】:

    标签: ssl openssl


    【解决方案1】:

    Meta:我试图在超级用户中回答这个问题,但你删除了它。幸运的是,当我找到这个副本时,我的大部分工作仍然放在我没有关闭的草稿记事本中,否则我不会愿意做两次研究工作。

    s_client -showcerts 显示服务器发送的证书;根据 RFC,这应该是一个有效的向上顺序的链除了根可以(在 RFC2119 定义中,即允许但不特别推荐)被省略。但是,并非所有服务器都配置正确,有些可能会发送额外的、丢失的和/或乱序的证书。此外,根据所使用的 CA,可能有多个有效链,但服务器只能发送一个。 openssl 目前将只使用发送的链,但这将在 1.0.2 中很快改变,并且其他依赖者有时会找到与发送的不同的链。

    openssl:如果接收到的链是完整的,并且可能包括在所使用的信任库中的根(其默认位置取决于系统或构建,并且在任何情况都可以被覆盖)然后openssl客户端将验证它是否正常-除非它已过期或被撤销并且该信息可用,但通常它不可用。在这种情况下,您可以编写一个客户端程序,该程序在设置 cert-verify 回调 函数后连接,该函数输出验证循环处理的完整证书或您想要的其他信息,而不是 @ 987654323@ 使用一个回调,该回调记录(仅)depth=n 行中的主题名称,您可以在示例中看到它包括此处链中的所有 4 个证书。 openssl 是开源的,所以像 s_client 这样的客户端程序可能是 s_client 的修改副本(在这种情况下特别是 s_cb.c)。

    Java 也可以做到这一点,而且写起来要短一些,但需要安装 Java。如果接收到的链针对使用的信任库中的 anchor 进行验证(默认为一组公共根,但可以修改或覆盖,并且可以具有非根锚),您同样可以编写一个程序(可能是 20 行)来连接使用 HandshakeCompletedListener 转储来自event.getPeerCertificates() 的信息。但是,如果链未验证,Java 会以异常中止握手并且您根本不会获得任何证书,这与 openssl 情况不同,您可能会在错误发生之前获得部分信息 - 加上 openssl 的检查,至少在默认情况下,是反正没那么严格。

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

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

    【讨论】:

    • 嘿!对不起,我的另一个问题被核了!
    【解决方案2】:

    您会在 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||$!;
    

    【讨论】:

      猜你喜欢
      • 2015-08-22
      • 1970-01-01
      • 1970-01-01
      • 2021-09-12
      • 2022-01-03
      • 1970-01-01
      • 2018-04-27
      • 2016-11-05
      • 2020-12-07
      相关资源
      最近更新 更多