从sslyze看TLS证书的点点滴滴

纵观眼下,https已经深入大街小巷,成为网络生活中不可或缺的一部分了。提到了https,我们又不得不想到TLS(SSL),而提到了TLS,我们又不得不提到一个让人捉摸不透的东西:TLS证书。

关于证书的原理,这里就不展开了,简言之,就是服务器让客户端放心,我就是你要找的那个,不信你看看那谁谁给开的介绍信。

在日常使用或者开发中,我们有时会不可避免地需要分析诊断TLS证书,而分析证书呢,有一款非常不错的开源工具你应该不会错过:sslyze

这篇文章旨在提纲挈领地跟大家一起通过使用sslyze进行TLS证书分析诊断的结果,从而熟悉下证书诊断的点点滴滴的知识。证书相关的知识比较庞杂,说点点滴滴也有点寒酸,充其量只能是些皮毛,算是抛砖引玉吧。姑且先让我们顺着sslyze的思路,边走边聊吧。

1. 安装及使用

sslyze是一个python项目,安装使用比较容易:

pip install --upgrade sslyze

如果想使用它来进行对某个域名对应的证书进行诊断,比如说我想知道www.baidu.com这个域名对应的证书是不是合法。大家知道,证书是服务器传给客户端的,而在什么时候传的呢,那是在TLS握手的时候传的,而我们知道TLS是建立在TCP之上的,要进行TLS握手,必须先有了TCP连接,而要进行TCP连接,必须知道五元组(源目地址、端口和协议),关于这个目的地址,就有文章可做了,万一host这个证书是在不同的服务器上、对应于不同的ip呢?比如说,www.baidu.com这个域名对应了10个ip,我更新了证书了,但是我不确定某个服务器ip对应的证书是不是跟其他的一样正确,那我可能需要对某个特定的ip进行诊断,让sslyze告诉我,你去跟这个ip通信,拿到它传给你的证书,看看是不是正确。这时,需要这么办:

sslyze --certinfo www.baidu.com{36.152.44.96}

其中,36.152.44.96是对应于www.baidu.com的一个ip。

至于其输出是什么样,我们一会再说。

2. 输出解析

我们通常使用sslyze时,可能会用到两种输出。一种是一般的命令行输出,其优点是,简洁、可读性好。另外一种呢,是JSON输出,这种输出格式机器友好,便于编程解析,因此也不可或缺。

本来呢,两种输出常理之中应该仅仅是格式差异,结果应该是换汤不换药吧。可是,sslyze的这两种输出内容还真是不一样,而且差别还不小,虽然够不上互补,但也足以让初学者难于一一对应上。所以我们还得分别说道说道。

需要首先说明的是,我们以下的输出是基于sslyze版本2.1.4,而openssl版本是2.8.3.

2.1 命令行文本输出

在上文中,我们已经提及了这个命令,这里重复下:

sslyze --certinfo www.baidu.com{36.152.44.96}

其输出如下:

 1  AVAILABLE PLUGINS
 2  -----------------
 3 
 4   SessionRenegotiationPlugin
 5   OpenSslCipherSuitesPlugin
 6   FallbackScsvPlugin
 7   CertificateInfoPlugin
 8   HeartbleedPlugin
 9   SessionResumptionPlugin
10   EarlyDataPlugin
11   CompressionPlugin
12   OpenSslCcsInjectionPlugin
13   RobotPlugin
14   HttpHeadersPlugin
15 
16 
17 
18  CHECKING HOST(S) AVAILABILITY
19  -----------------------------
20 
21    www.baidu.com:443                       => 36.152.44.96
22 
23 
24 
25 
26  SCAN RESULTS FOR WWW.BAIDU.COM:443 - 36.152.44.96
27  -------------------------------------------------
28 
29  * Certificate Information:
30      Content
31        SHA1 Fingerprint:                  d1f6323db6f2ec81e7023690f49b2d91e0c3993a
32        Common Name:                       baidu.com
33        Issuer:                            GlobalSign Organization Validation CA - SHA256 - G2
34        Serial Number:                     13905183944940287882518820211
35        Not Before:                        2019-05-09 01:22:02
36        Not After:                         2020-06-25 05:31:02
37        Signature Algorithm:               sha256
38        Public Key Algorithm:              RSA
39        Key Size:                          2048
40        Exponent:                          65537 (0x10001)
41        DNS Subject Alternative Names:     ['baidu.com', 'click.hm.baidu.com', 'cm.pos.baidu.com', 'log.hm.baidu.com', 'update.pan.baidu.com', 'wn.pos.baidu.com', '*.91.com', '*.aipage.cn', '*.aipage.com', '*.apollo.auto', '*.baidu.com', '*.baidubce.com', '*.baiducontent.com', '*.baidupcs.com', '*.baidustatic.com', '*.baifae.com', '*.baifubao.com', '*.bce.baidu.com', '*.bcehost.com', '*.bdimg.com', '*.bdstatic.com', '*.bdtjrcv.com', '*.bj.baidubce.com', '*.chuanke.com', '*.dlnel.com', '*.dlnel.org', '*.dueros.baidu.com', '*.eyun.baidu.com', '*.fanyi.baidu.com', '*.gz.baidubce.com', '*.hao123.baidu.com', '*.hao123.com', '*.hao222.com', '*.im.baidu.com', '*.map.baidu.com', '*.mbd.baidu.com', '*.mipcdn.com', '*.news.baidu.com', '*.nuomi.com', '*.safe.baidu.com', '*.smartapps.cn', '*.ssl2.duapps.com', '*.su.baidu.com', '*.trustgo.com', '*.xueshu.baidu.com', 'apollo.auto', 'baifae.com', 'baifubao.com', 'dwz.cn', 'mct.y.nuomi.com', 'www.baidu.cn', 'www.baidu.com.cn']
42 
43      Trust
44        Hostname Validation:               OK - Certificate matches www.baidu.com
45        Android CA Store (9.0.0_r9):       OK - Certificate is trusted
46        Apple CA Store (iOS 13, iPadOS 13, macOS 10.15, watchOS 6, and tvOS 13):OK - Certificate is trusted
47        Java CA Store (jdk-13.0.2):        OK - Certificate is trusted
48        Mozilla CA Store (2019-11-28):     OK - Certificate is trusted
49        Windows CA Store (2019-11-10):     OK - Certificate is trusted
50        Symantec 2018 Deprecation:         WARNING: Certificate distrusted by Google and Mozilla on September 2018
51        Received Chain:                    baidu.com --> GlobalSign Organization Validation CA - SHA256 - G2
52        Verified Chain:                    baidu.com --> GlobalSign Organization Validation CA - SHA256 - G2 --> GlobalSign Root CA
53        Received Chain Contains Anchor:    OK - Anchor certificate not sent
54        Received Chain Order:              OK - Order is valid
55        Verified Chain contains SHA1:      OK - No SHA1-signed certificate in the verified certificate chain
56 
57      Extensions
58        OCSP Must-Staple:                  NOT SUPPORTED - Extension not found
59        Certificate Transparency:          WARNING - Only 2 SCTs included but Google recommends 3 or more
60 
61      OCSP Stapling
62                                           NOT SUPPORTED - Server did not send back an OCSP response
63 
64 
65  SCAN COMPLETED IN 0.85 S
66  ------------------------

1-14行,是sslyze自己可以使用的一些plugin,如果不打算自己enable或者编写plugin的话,我们暂且先略过。

18-21行,表示当前诊断域名www.baidu.com对应的ip是36.152.44.96,这也没有什么可争议的,因为是我们预先指定的,假如我们不指定,这里或许就有意义了,会给你看通过DNS解析出来的ip地址,即当前我们诊断的是哪个ip。

29行向下的Certificate Information,才是我们想知道的东西,让我们来一一查看。

  • Contents

位于输出结果的30至41行,主要告诉我们关于证书本身的一些事情,我们要知道,所有的公开的证书都是由一个权威的机构给签发的,这个机构叫CA(certificate authority),它是一个公开的第三方,是具有一些公信力的第三方机构。

大家知道,我们的系统或者浏览器在出厂的时候,就内置了一些CA,比如说我用的MacBook,刚到手就已经为我内置了一系列世界上公认的一些CA了,这样可以避免你从一些不安全的地方来获取他们,因为,这些CA是所有信任的原点,他们不安全,那么所有的TLS就都不安全了。这些CA的作用就是来验证,这些证书是不是自己签发或者信任的。如果一个CA,比如说GlobalSign Organization Validation CA告诉你说,没问题的,这个是我签发的,你就放心好了。那你就可以相信它了。

既然内置了这么些CA,我们跟服务端TLS通信前,收到了证书,怎么知道找哪个CA来验证呢?总不至于把所有的CA都验证一遍吧?不至于,那样实在太低效了,你收到的每个证书都会直接告诉你,你应该找谁去验证,在哪里告诉的呢?33行有个Issuer字段。我们这里是GlobalSign Organization Validation CA - SHA256 - G2,告诉我们是GlobalSign的CA签发的,SHA256签名的,那后面的G2是什么意思呢?"G"代表Generation,如果这个CA想换一个chain的话,那直接变成G2、G3就好了。

我们还可以看到这个证书只有在2019-05-09 01:22:02至2020-06-25 05:31:02期间才是合法的,想要伪造出非法证书也很容易,只要把你的系统时间改到这个之外就可以了。公钥是RSA的,签名是SHA256的。

最有意思的是最下面那个DNS Subject Alternative Names,可以看到这么多的域名使用着和"www.baidu.com"一样的证书。 

  • Hostname Validation

这个是其实是openssl内置的一个基础功能,目的是验证证书里说的hostname是不是跟你所请求的一致。比如你或者了一个证书A,是合法的证书,但是它不是baidu.com的证书,一下就被识破了,你不能用它来和baidu.com的服务器通信。

  • Android/Apple/Java/Mozilla CA Store

我们前文也说过,任何一个公开的平台或者浏览器,它都必须提供一系列CA集合,用来方便绝大多数一般用户安全连接网络。这样,每一个平台自己的CA集合就或多或少地跟其他的平台在这个CA集合上有了差异,这里sslyze就模拟了这些系统或者浏览器的CA集合,来验证假设用户在这些平台上,通过这些系统或者平台自带的CA集合,是不是得到证书被信任的结果。

  • Symantec 2018 Deprecation

我见过的每一个证书验证在这项都会出现这么一个WARNING,因此,可以断定这项你就不要担心了吧。其实,这一项涉及了一个非常狗血的故事,Symantec原本是一个比较大
的CA供应商,在2018年的时候,Google对Symantec签发证书的方式已经非常不满到忍无可忍了,于是乎,发布了一个声明,决定到2018年某个时间点,就在自己的浏览器上判定Symantec的证书都是不合法的,随后得到了Mozilla的响应,然后Symantec就比较被动了,你签发的证书已经遭到了两大浏览器的抵制了嘛,然后无奈之下,只得把自己
的签发证书这块业务给卖掉了,表示从此金盆洗手,不玩这个了。你现在见到的Symantec证书已经是另外一个公司在运营的了,而且,你也不用担心,因为2018年早就过去了,原来那个Symantic签发的被认定为非法的证书要么整改了要么已经过期了,所以呢,任何健在的证书你都不用担心这个问题啦。

  • Received/Verified Chain

要了解这两个Chain,我们先得了解什么是信任链(Trust Chain)。我们刚也提到过,这世间的著名的*CA也就那么几家,而这世间的证书可谓难以计数,如果每一个证书的申请和维护都由这几家*CA来完成的话,*CA可真是烦透了。这时候,分治的思想就来了,*CA那是大咖啊,他认证了一些小弟,如果谁要找他,他会说大事找我行,小事就不要找我了,找我的小弟去,跟找我效果差不多。这里他的这些小弟都是他给背书的,信用自然没的说,你信任了*CA,也就自然信任了他的小弟。这些小弟也叫中间证书(Intermediate Certificate),提供了一个引导用户到*CA的路径,而且小弟可能还不止一级,小弟还可以信任小小弟,这就形成了一个链,这个链叫做“信任链”。

这具体是怎么操作的呢?我们来看下图:

从sslyze看TLS证书的点点滴滴

用户在访问baidu.com的时候,首先通过DNS解析拿到某个服务器IP,连接到某个服务器,在TLS握手过程中,首先获得baidu.com的证书,用户一看它的Issuer,是GlobalSign Organization Validation CA - SHA256 - G2,而这也不是已知的*CA,于是又问服务器要GlobalSign Organization Validation CA - SHA256 - G2证书(实际是跟baidu.com证书一起发送给用户的,这里只是为了让大家容易理解一点),再看它的Issuer,一看是GlobalSign Root CA,这是他知道的一个*CA,那就到此为止了,不必再麻烦服务器了。再回头看下,我们刚才接收到了几次证书?一共是两次,baidu.com -> GlobalSign Organization Validation CA - SHA256 - G2,两次到达了*CA,这个链就是所谓的Received Chain。由此可见,服务器不光要保存baidu.com这种域名对应的证书,还要保存其中间证书,因为用户也需要从它这里获得。

证书都已经齐活了,那用来干嘛呢?那自然是用来验证了。首先还是验证baidu.com的有效性,从它的Issuer字段知道,它是由GlobalSign Organization Validation CA - SHA256 - G2签发的,那我们就拿到GlobalSign Organization Validation CA - SHA256 - G2证书,获取它的公钥,然后利用公钥算法,来验证baidu.com的签名,由于公私钥算法的严密性,签名是非常难以伪造的,如果我们验证出了签名是正确的,就可以认为该证书是GlobalSign Organization Validation CA - SHA256 - G2给签发的。但是这个GlobalSign Organization Validation CA - SHA256 - G2是刚才你服务器那里获得的,这不等于你自己证明你自己吗,没关系,你可以验证它的Issuer,也就是GlobalSign Root CA,这个是*CA,本地有它的证书,那拿过来照着上面的做法来一通,就可以知道GlobalSign Organization Validation CA - SHA256 - G2是不是GlobalSign Root CA 给签发的了,验证通过了,那证明就是GlobalSign Root CA签发了GlobalSign Organization Validation CA - SHA256 - G2,而GlobalSign Organization Validation CA - SHA256 - G2又签发了baidu.com,从而证明你拿到的baidu.com是有效的。刚刚我们走完了一个链,就是baidu.com -> GlobalSign Organization Validation CA - SHA256 - G2 -> GlobalSign Root CA,为了验证而为之的,所以就是Verifed Chain了。

以上过程比较简化和粗糙,如果能够说明白了,而且还不晕乎的话,那么我们就来看看一个实际的而且更加详实的证书解析结果吧。在本地运行如下openssl命令:

openssl s_client -showcerts -connect www.baidu.com:443

输出结果如下:

 1 CONNECTED(00000006)
 2 depth=2 C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign Root CA
 3 verify return:1
 4 depth=1 C = BE, O = GlobalSign nv-sa, CN = GlobalSign Organization Validation CA - SHA256 - G2
 5 verify return:1
 6 depth=0 C = CN, ST = beijing, L = beijing, OU = service operation department, O = "Beijing Baidu Netcom Science Technology Co., Ltd", CN = baidu.com
 7 verify return:1
 8 ---
 9 Certificate chain
10  0 s:/C=CN/ST=beijing/L=beijing/OU=service operation department/O=Beijing Baidu Netcom Science Technology Co., Ltd/CN=baidu.com
11    i:/C=BE/O=GlobalSign nv-sa/CN=GlobalSign Organization Validation CA - SHA256 - G2
12 -----BEGIN CERTIFICATE-----
13 MIIJrzCCCJegAwIBAgIMLO4ZPBiCeOo+Q3VzMA0GCSqGSIb3DQEBCwUAMGYxCzAJ
14 BgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTwwOgYDVQQDEzNH
15 // ... 省略若干行...
16 oZ0B5qslIww7JAJAWCT/NAKLlGEQaC+2gOPQX0oKpwLSwJg+HegCyCdxJrKoh7bb
17 nRBHS8ITYjTG0Dw5CTklj/6i9PP735snPfzQKOht3N0X0x8=
18 -----END CERTIFICATE-----
19  1 s:/C=BE/O=GlobalSign nv-sa/CN=GlobalSign Organization Validation CA - SHA256 - G2
20    i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
21 -----BEGIN CERTIFICATE-----
22 MIIEaTCCA1GgAwIBAgILBAAAAAABRE7wQkcwDQYJKoZIhvcNAQELBQAwVzELMAkG
23 A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
24 b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xNDAyMjAxMDAw
25 // ... 省略若干行...
26 K1pp74P1S8SqtCr4fKGxhZSM9AyHDPSsQPhZSZg=
27 -----END CERTIFICATE-----
28 ---
29 Server certificate
30 subject=/C=CN/ST=beijing/L=beijing/OU=service operation department/O=Beijing Baidu Netcom Science Technology Co., Ltd/CN=baidu.com
31 issuer=/C=BE/O=GlobalSign nv-sa/CN=GlobalSign Organization Validation CA - SHA256 - G2
32 ---
33 No client certificate CA names sent
34 Server Temp Key: ECDH, P-256, 256 bits
35 ---
36 SSL handshake has read 4265 bytes and written 322 bytes
37 ---
38 New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
39 Server public key is 2048 bit
40 Secure Renegotiation IS supported
41 Compression: NONE
42 Expansion: NONE
43 No ALPN negotiated
44 SSL-Session:
45     Protocol  : TLSv1.2
46     Cipher    : ECDHE-RSA-AES128-GCM-SHA256
47     Session-ID: 42FD0DF68EDA274407EC33AD8B9E98177D10CBE8DA1F07E03F6E03A0CDB58FC3
48     Session-ID-ctx:
49     Master-Key: F863A3EB7527D0EC1F752C26CF8670749F7C02BFE451584E16CAAED22A414374DA5F06A24434CA1B7B69781D7C14AB7D
50     TLS session ticket:
51     0000 - b9 e4 f4 ab 7d 8a 32 7d-f3 56 1b 04 b6 62 89 f9   ....}.2}.V...b..
52     0010 - ff c0 b8 14 dd 2e 87 94-6c 16 c6 28 5a bd a1 e0   ........l..(Z...
53     0020 - ae c7 20 c8 7b c5 10 57-f5 6d 7f 40 a9 75 ed 7b   .. .{..W.m.@.u.{
54     0030 - cd 3d 3e 1b c0 c5 86 c7-24 55 ff d4 2c b2 58 e1   .=>.....$U..,.X.
55     0040 - 48 7f b9 e7 b5 c5 e9 0e-3b df 44 ce 5e 1c 03 9f   H.......;.D.^...
56     0050 - 92 a1 9a ec 93 d1 bd f3-f1 89 81 a7 d0 f4 ce 38   ...............8
57     0060 - 4d 87 17 99 d9 d4 eb 4c-46 75 8f e2 4b 62 03 18   M......LFu..Kb..
58     0070 - 63 86 83 e9 d6 54 0b ea-b8 ea bf 87 cc e6 4b c6   c....T........K.
59     0080 - 34 19 0f b0 25 2c a2 66-a4 5f 99 90 bd 61 00 74   4...%,.f._...a.t
60     0090 - 3e 45 f7 92 e9 2e f9 6c-12 c1 35 8e 4f 3c dd 7a   >E.....l..5.O<.z
61 
62     Start Time: 1585465282
63     Timeout   : 7200 (sec)
64     Verify return code: 0 (ok)
65 ---
66 closed

看看以上openssl输出结果的第9行以下,Certificate chain那里,可以看到我们这里从服务器端接受到了两个证书,我们应当注意到以下几点:

  • 证书0的名字(Subject)是baidu.com(CN), 签发者(Issuer)是GlobalSign Organization Validation CA - SHA256 - G2
  • 证书1的名字是证书0的签发者,其签发者是GlobalSign Root CA
  • 没有收到GlobalSign Root CA的证书
  • Received Chain Contains Anchor

这里所谓的包含Anchor,其实是服务器端传递给客户端的证书中,包含了根证书。这是不允许的,如果包含了根证书,那会是怎么样,根证书是自签名的,也就是它是可以自己验证自己的,而且是用你服务器传过来的验证,那这还有什么验证的价值呢?所以,看到了这个,一定是证书出了问题了,告诉证书管理员,把Chain中的根证书给去掉,根证书客户端那里有的,用不着麻烦服务器。 

  •  Received Chain Order

如果理解了 Received/Verified Chain中所说的,那这里就很容易理解了。就是告诉你接收到的Chain中的顺序不对了。我们先不说不对的顺序是什么,我们先说说什么是对的吧:

  • 首先是域名对应的证书
  • 其次是中间证书
  • 前一个证书的Issuer必然对应后一个证书的Subject
  • 最后一个证书的Issuer必然是某个Root CA

然后我们来探讨一种不对的情况,就是,如果我服务器端处于某种目的,需要准备多个Certificate Path,即最终的Root CA是多个。假设以上baidu.com的例子,现在的Root CA是GlobalSign Root CA,假如服务器那边还想为本地没有这个Root CA的用户做点什么,他想加一个比如说Baltimore CyberTrust Root,这样用户只要拥有两个CA中的一个就会验证成功。而我们知道中间证书的作用是形成一个Chain来连接域名证书和Root CA的,那么这样就会形成两条路径,可能接受到了两个不同的中间证书,这样是合理的,但是却违背了我们以上说的那个被期望的顺序了,即两个中间证书中的前一个证书的Issuer不对应后一个的Subject,因而会被判定为"Certificate chain out of order!".

  •  Verified Chain contains SHA1

以上我们已经知道,证书之间是通过“签名”来构建这个信任链的。因而,“签名”是这个信任链安全的核心,而“签名”一个证书,则需要签发者拥有一个绝密的只有自己才能知道的私钥和一个公开的、用来验证签名正确性的私钥,还需要一个单向哈希算法,这样用自己的公钥和需要签名的内容通过这个哈希算法得出一个签名,任何人可以通过公开的公钥要验证,从而确定这个证书是不是他签发的。刚刚提到这个哈希算法的单向性是非常重要的,因为,如果非常容易地通过签名和公钥来推算出这个私钥的话,那就可以任意伪造证书了。相比较而言,SHA1就是这种哈希算法中比较弱的了,而SHA256等相对比较强,难以攻破。我们再来看这个检查项,它表示在验证证书的过程中,是否包含了SHA1来签发的证书,如果有,证明这个信任链是不够安全的。

  •  OCSP Must-Staple

要理解这个,我们首先要理解OCSP。OCSP即Online Certificate Status Protocol, 这个是用来干吗的呢,还得从历史说起。话说,自有TLS证书的时候,就有了一个问题,就是万一某个本来合法的证书泄露了(Leak),变得不安全了,这个证书的所有者,就是使用这个TLS证书来跟客户端打交道的那些网站等服务器所有者,他们所要做的第一件事就是通知这个证书的签发机构,帮我吊销这个证书吧,免得不法分子正在冒充他跟客户端通信。证书的签发机构(CA)就会标记这个证书被吊销了(Revoke)。客户端怎么知道哪些证书被吊销了呢?这时,CA提供一个机制,就是定期把所有被他吊销的证书打包,然后客户端定期下载,当客户端下次拿到一个证书后,就会跟这个吊销的集合进行比对,来确认证书是否被吊销。问题来了,定期下载,太频繁吧,客户端嫌麻烦,不频繁吧,这容易漏掉某个刚刚被吊销的,而且,被吊销的证书每天有千千万,这些证书原来对应的网站可能用户绝大多数都访问不到,这低效性可见一斑。怎么办呢?可能你已经想到改进措施了,就是用户每次拿到一个证书后,自己到这个CA去验证一下,看看有没有被吊销,这就形成了OCSP,这样确实能够避免了用户下载过多没有用的证书,也避免了因为时效性问题导致的把被新吊销的误判。可是,这样也不是没有成本的,用户每次TLS会话都需要访问CA来次检查,对用户太低效,对CA服务器那边也是压力,而且用户看了什么网站都需要向CA汇报一次,那也就等于CA可以一直监控用户的网络行为,这样用户也是不开心的。那这样改进下,咱也不用客户去检查了,把这个负担转嫁给服务器吧,服务器每隔一段时间都去CA那边报道下,让他给像签发证书一样签发一个证明,表示这个证书没有过期,每次客户端来访问的时候,服务器就把这个证明连同证书一起发给客户端,客户端拿CA的公钥轻松一验证就知道真假,也不用去请求CA服务器了,服务器这边也只要隔一段时间才去CA请求一次这个证明就能保证用户拿到的证书都不过期的,是不就是皆大欢喜。这里的这个证明我们叫做Staple,这个TLS证书的扩展功能就是OCSP Must-Staple。用户在TLS握手的时候,看到这个标记了,就知道服务器传过来的证书中包含了staple,那客户端验一下就可以了。

  • Certificate Transparency 

所谓Certificate Transparency,其实就是一个开放标准用以限制或者要求CA不会乱签发证书,特别是对于一个域名相关的证书进行乱签发,比如一个CA给baidu.com签发了证书,如果他再给另外一个组织签发next.baidu.com,这可就乱套了,所以baidu.com的管理员需要有某种方法,来监控(或者某种意义上说是监督)这个CA,要按套路。为了保证证书的透明度,证书界出了一个“正义联盟”,它推出了一个Certificate Transparency Project,主要达成以下目的:

  1. 让一个CA不可能或者说很难签发一个域名下的证书而不被这个域名的管理员发现
  2. 提供一个审计和监控平台,这样域名管理员和CA就可以轻易地发现某个证书被错误地或者恶意地签发了
  3. 方便地告诉用户,某个域名被错误地或者恶意地使用了

它是如何保证工作的呢?这个项目的核心就是使用一个append-only log系统,来保存所有的证书记录,每个证书在签发的时候一定要向这个系统提交这个证书的记录,所以每个证书签发成功的时候返回一个记录在证书中回执,就是Signed Certificate Timestamp (SCT),这是一个凭证,表示这个log系统已经接受了这个证书的信息了。

Google的Chrome作为这方便的先锋,被业界认可,他倡导了CA的一些规范,总结下来主要有如下几点:

  1. Certificate Extension:证书中要包含SCT
  2. TLS Extension:SCT信息通过一个TLS扩展字段signed_certificate_timestamp包含在TLS握手中
  3. OCSP Stapling:CA必须支持域管理者使用OCSP Stapling

假如这个证书缺少其中一项或者几项的功能,你或许会看到类似这样的信息“WARNING - Only 2 SCTs included but Google recommends 3 or more”。

  • OCSP Stapling

这一项在上面OCSP Must-Staple中已经介绍过了,OCSP Must-Staple事实上是证书的一个扩展,而OCSP Stapling是服务器的一个功能,即是不是在客户端向服务器发出stapled OCSP请求的时候给出相应的回应。

2.2 JSON输出

我们先前也提到过,JSON输出便于代码解析,因此在sslyze这个工具使用中场景甚至多余命令行输出。对应于上面的例子,这里我们用JSON输出一遍:

sslyze --certinfo --json_out=- www.baidu.com

其结果如下所示(注:这里结果非常详细,但也非常冗长,为了不影响观看,对某些内容做了折叠,请大家注意行号):

从sslyze看TLS证书的点点滴滴

 剔除一些一眼就能知道的内容,上面的输出结果中,我们可以看到主要有certinfo和server_info两块内容,而其中server_info又都是server本身的一些信息或者再TLS握手中拿到的信息,与证书本身关联不大,因而,我们还是把注意力集中在certinfo上吧。

  • leaf_certificate_has_must_staple_extension

 跟命令行输出结果中“OCSP Must-Staple”对应,表示证书中是否含有OCSP must-staple扩展。

  • leaf_certificate_is_ev

我们能遇到的证书可以分为三类,即Domain Validated (DV), Organization Validated (OV)和Extended Validated (EV),我们先对比下他们的差异:

    • DV:
      • 单个域名级别的认证
      • 便宜
    • OV:
      • CA在签发这个证书的时候验证公司信息
      • 安全性比DV高
      • 比DV稍贵
    • EV:
      • 比上面两种安全性都高
      • 用户键入浏览器时会显示公司名,且显示为绿色(看浏览器)

对比了以上之后,不用我说了吧,EV是对用户最好的,对服务提供商而言,除了贵,其他都好。

  • leaf_certificate_signed_certificate_timestamps_count

关于Signed Certificate Timestamp (SCT)上面已经介绍过了,这里可以认为跟上文所述的“Certificate Transparency”类似,表示含有多少个SCT检查项。

  • leaf_certificate_subject_matches_hostname

即域名跟证书是否匹配,跟上文的“Hostname Validation”相类似。

  • ocsp_response/ocsp_response_is_trusted/ocsp_response_status

用户要求服务器发送Stapled OCSP时,服务器的返回,以及本地验证结果如何,具体道理在命令行输出“OCSP Stapling”中我们提及过,他们是类似的。

  • path_validation_error_list/path_validation_result_list

 在命令行输出分析中,我们也提及过,在不同的平台上Root CA的集合可能不同,而从域名证书 -> 中间证书 -> Root CA 的路径可能会有差别。“path_validation”实际就是模拟各个平台或者系统对其验证的路径的遍历结果,如果验证失败了,就会追加到“path_validation_error_list”中,如果成功了,自然会在“path_validation_result_list”中。

  • received_certificate_chain

关于“Received Chain”,我觉得上面已经啰啰嗦嗦一大堆了,在你觉得烦躁前我决定就此打住。需要看详细的Received Chain,这里提供了一个比较友好的方式,而不必用openssl了。

  • received_chain_contains_anchor_certificate

与命令行输出中“Received Chain Contains Anchor”中的意思是一致的。

  • received_chain_has_valid_order

与命令行输出中“Received Chain Order”类似。

  • verified_certificate_chain

选择其中一个path进行验证的结果,这一项可以看到上面所说的详细的Certificate Chain。

  • verified_chain_has_legacy_symantec_anchor 

 与命令行输出结果中“Received Chain Contains Anchor”一致。

  • verified_chain_has_sha1_signature

 与命令行输出结果中“Verified Chain contains SHA1”一致。

3. 参考文献

[1] https://docs.microsoft.com/en-us/windows/win32/seccrypto/certificate-chains

[2] https://blog.qualys.com/ssllabs/2017/09/26/google-and-mozilla-deprecating-existing-symantec-certificates

[3] https://cheapsslsecurity.com/p/what-is-ssl-certificate-chain/

[4] https://knowledge.digicert.com/solution/SO16297.html

[5] https://scotthelme.co.uk/ocsp-must-staple/

[6] https://www.globalsign.com/en/blog/what-is-certificate-transparency

[7] https://comodosslstore.com/resources/dv-vs-ov-vs-ev-ssl-which-certificates-are-good-for-site-security/

上一篇:关于win7 无法识别sha256签名导致驱动无法安装的问题


下一篇:Docker快速入门(一)