假设一个 TLS 证书链的验证。假设链有证书 ABCD,其中 D 是根证书,A 由 B 签名,B 由 C 签名,C 由 D 签名。
假设发现中间证书 B 已经内置在浏览器中。也就是说,检查 A,发现它是有效的(并由 B 签名)并且 B 被内置到浏览器中。
(1) 链的验证是在此结束还是继续直到我们到达 D?
(2) 当服务器向浏览器提供它的证书链时,它是否也提供根证书 D 或只提供 ABC?
假设一个 TLS 证书链的验证。假设链有证书 ABCD,其中 D 是根证书,A 由 B 签名,B 由 C 签名,C 由 D 签名。
假设发现中间证书 B 已经内置在浏览器中。也就是说,检查 A,发现它是有效的(并由 B 签名)并且 B 被内置到浏览器中。
(1) 链的验证是在此结束还是继续直到我们到达 D?
(2) 当服务器向浏览器提供它的证书链时,它是否也提供根证书 D 或只提供 ABC?
(1) 链的验证是在此结束还是继续直到我们到达 D?
它取决于证书链接引擎(CCE) 的实现。不同的平台有不同的实现,可能不支持RFC5280中描述的所有推荐/强制验证逻辑。
证书信任需要以自签名形式呈现的链结点(我们将此类证书称为根 CA 证书)。由于证书 B 不是自签名的(由 C 签名),因此在获取并验证 C 和 D 之前,ABCD 链是不可信的。所以,这个问题的答案是:链继续验证到根。
如果我们谈论微软的实现(只是我熟悉的一个例子),他们的 CCE 构建一个或多个链(尽可能多)而不执行立即验证。他们只是获取证书并尝试执行基本规则以将每个证书绑定到链中的正确位置。构建所有链后,每个链都根据 RFC5280 中描述的规则进行验证。验证后,可能存在多个受信任且有效的链的情况。CCE 使用自己的选择逻辑从一组链中只选择一个链。
当我们谈论浏览器中的证书存储时,它们习惯于:
Authority Information Access扩展的能力,这意味着 SSL 客户端只能从两个来源获取 CA 证书:SSL 握手、本地证书存储。(2) 当服务器向浏览器提供它的证书链时,它是否也提供根证书 D 或只提供 ABC?
它取决于 Web 服务器的实现。来自RFC 5246 §7.4.2的参考:
certificate_list 这是证书的序列(链)。发件人的证书必须在列表中排在第一位。后面的每个证书必须直接证明它前面的证书。因为证书验证要求根密钥是独立分发的,所以可以从链中省略指定根证书颁发机构的自签名证书,假设远程端必须已经拥有它才能在任何情况下验证它。
RFC 建议根 CA 证书可以或不可以发送给客户端。因此,在开发 SSL 客户端时,您应该期望根证书可能会沿着链传送。两个主要的 Web 服务器:Apache 和 IIS 默认情况下不会在 SSL 握手期间发送根证书。
1)如果中间证书(B)是可信的——也就是说,它是一个有效的签名证书,没有过期,没有被篡改,也没有被撤销——那么它在信任库中就足够了,TLS客户端不需要继续上链以验证叶子证书。
但是,“不被篡改”的事情需要有一个受信任的证书已经签署了中间证书。现在,中间证书可以是自签名的,就像根证书一样,除了作为根证书链的一部分。在这种情况下(假设签名签出),无需验证中间证书上方的链。
一些客户端甚至可能不去验证证书上是否有有效的签名(它在信任库中,所以理论上是值得信赖的)或者它没有被撤销(很多旧的浏览器没有检查撤销默认情况下,假设它们将使用更新的已撤销证书列表进行更新,而不再位于信任库中)。但是,在实践中,您应该假设大多数客户都检查了这两件事(即使是自签名的有效签名,也没有被撤销)。
2)这完全取决于服务器。通常会提供除根证书之外的所有内容,但有些服务器会发送整个链。如果您使用Qualys SSLLabs之类的网站,它会向您显示服务器发送的证书。该站点似乎发送了两个证书 - 一个通配符叶*.stackexchange.com和一个“服务器 CA”中间证书,但不发送根证书(这是一个 DigiCert EV 根 CA,并签署了中间证书)。但是,其他一些站点确实发送了完整的链;如果您这样做,SSLLabs 会对其进行标记,但通常这只是一种浪费。