【面试补缺(2)】HTTPS握手阶段浏览器对服务端证书的验证过程

在学习HTTPS协议握手过程的时候,在接收服务端Server Hello数据包的时候会包含有服务端的证书,然后浏览器需要对这个证书进行验证,但是很多文章都对这个验证过程一笔带过了,所以这里来总结一下。

参考资料

  1. Browsers and Certificate Validation
  2. HTTPS通信中的身份认证机制

为什么要验证这个证书

在HTTPS连接中,证书是服务端身份的证明,另外证书中的公钥也是用来加密premaster key的重要依据,因此,保证必须保证证书是由服务员原汁原味传过来的,而不是中间攻击者伪造的证书。

证书和X.509格式

证书是属于数字文件,这意味着他们需要遵循文件格式来存储信息(例如签名,密钥,发行者等)。虽然私有的PKI配置可以为证书实现任何格式,但公开信任的PKI(即浏览器信任的PKI)必须符合RFC 5280,因此我们需要使用X.509 v3格式。

X.509v3证书由三部分组成:

  • tbsCertificate (to be signed certificate),待签名证书
  • SignatureAlgorithm,签名算法
  • SignatureValue,签名值

tbsCertificate又包含10项内容,在HTTPS握手过程中以明文方式传输:

  • Version Number,版本号
  • Serial Number,序列号
  • Signature Algorithm ID,签名算法ID
  • Issuer Name,发行者
  • Validity period,有效时间
  • Subject name ,证书主体名称
  • Subject Public Key Info ,证书主体公钥信息,包含公钥算法和公钥值
  • Issuer Unique Identifier (optional),发行商唯一ID
  • Subject Unique Identifier (optional),主体唯一ID
  • Extensions (optional),扩展

认证路径和路径处理

CA使用私钥对其所有办法的证书进行加密签名。此类签名可以证明证书是由CA颁发的,并且证明证书在签名后没有被修改过。

CA通过持有相应公钥的自发证书(称为ROOT)来建立其签名秘钥的所有权,意思是CA证书链的ROOT证书是由CA自签生成的。CA必须严格的控制和遵守审核的过程来创建,同时root会派发Intermediate CA中间证书给中间商赚差价,就是我们常去购买证书的网站,让它们也有权利颁发证书。

ca-chain

由ROOT派生中间证书,再由中间证书派发我们使用的证书,给个证书都签署了序列中的下一个证书,这一系列证书就成为证书路径 (certification path),根称为信任锚(trust anchor),我们服务端的证书就称为叶(leaf)证书或者终端实体( end entity)证书

注意一点就是ROOT CA是内置在浏览器当中的。

路径构建

通常来说,浏览器必须查找多个证书路径,直到找到给定证书的有效证书路径。即使路径可能包含正确的链接能连到已知锚点的证书,但由于路径长度、域名、证书使用或者策略的限制,路径本身可能会被拒绝。

每当浏览器遇到新的证书执行构建和评估所有路径的过程都是消耗很大的。当然,对于现在的浏览器来说已经有各种优化来选择正确的证书路径,这部分在本篇文章暂时不表。

路径验证

在构建候选证书路径之后,浏览器会使用当前证书中包含的信息对这条路径进行验证。如果浏览器可以证明,从一个信任锚直接签名的证书开始,遍历到的每个证书对应的私钥都是用于颁发下一个证书(一直到叶证书)的话,那么这条路径就是有效。

路径验证算法

RFC 5280描述了浏览器遵循的标准算法,用以验证X.509证书的证书路径。

浏览器会从信任锚(就是根证书)开始去遍历路径中所有的证书,验证每个证书的基本信息和关键扩展。

如果遍历到路径中最后一个证书都没有错误的话,则该路径为有效,如果中间产生错误,则无效。

基本证书的处理

抛开证书扩展先不谈,来说说浏览器对证书验证的检查顺序:

1. 验证证书的完整性

浏览器读取证书中的tbsCertificate部分(明文),使用SignatureAlgorithm中的散列函数计算得到信息摘要,并利用tbsCertificate中的公钥解密SignatureValue得到信息摘要,然后对比双方的信息摘要,判断是否一致;如果一致,则成功;如果不一致,则失败。

比较

数字签名技术是将摘要信息用发送者的私钥加密,与原文一起传送给接收者。接收者只有用发送者的公钥才能解密被加密的摘要信息,然后用HASH函数对收到的原文产生一个摘要信息,与解密的摘要信息对比。如果相同,则说明收到的信息是完整的,在传输过程中没有被修改,否则说明信息被修改过,因此数字签名能够验证信息的完整性。

2. 验证证书的有效性

有效性是指验证证书的有效日期,浏览器会拒绝验证过期的证书。

3. 检查证书是否被吊销

RFC 5280建议CA为此目的使用吊销列表。

证书撤销清单(CRL)
CA定期发布带有时间戳的已签名的撤销证书列表,称为证书吊销列表(CRL)。CRL分布在公共可用的存储库中,浏览器可以在验证证书时获取并查阅CA的最新CRL。

该方法的一个缺陷是撤销的时间粒度限于CRL发布期。只有在计划更新所有当前发布的CRL之后,才会通知浏览器撤销。根据签名CA的策略,这可能需要一小时,一天甚至一周。

在线证书状态协议(OCSP)
获取撤销状态信息还有其他替代方法,最常用的是在线证书状态协议(OCSP)。

在标准文档RFC6960中描述,OCSP允许浏览器从在线OCSP服务器(也称为应答器)请求特定证书的撤销状态。正确配置后,OCSP更加直接,并避免上述CRL更新延迟问题。此外,OCSP Stapling还可提高性能和速度。

4. 浏览器验证发行者

证书通常会跟下面两个要素相关联:

  1. 发行人,拥有签名秘钥的实体(就是颁发证书的中间商)
  2. subject,指证书认证公钥的所有者

浏览器会检查证书颁发者字段跟路径中先前证书的subject比较是否相同。为了安全性,还会比较颁发者的必要和当前证书的秘钥是否相同。

5. 检查名称约束

会对证书颁发者有效性进行检查,检查颁发证书的是否属于CA公开信任的中间商,以防有第三方颁发有效的证书。

6. 检查策略约束

证书策略是CA发布的法律文档,正式详细说明了颁发和管理证书所遵循的程序。CA可能会根据一个或多个策略颁发证书,并且每个颁发的证书中都包含指向这些证书的证书,以便依赖方可以在决定信任该证书之前评估这些策略。

出于法律和运营原因,证书可以对其可能受到的策略施加限制。如果发现证书包含关键策略约束,则浏览器必须在继续之前验证它们。(但是,在现实世界中很少遇到关键的策略约束,因此本文的其余部分将忽略这些约束。)

7. 检查证书路径的有效长度

X.509 v3格式允许发行者定义证书可以支持的最大路径长度。这可以控制每个证书在证书路径中的放置距离。这实际上很重要 - 浏览器曾经忽略了认证路径的长度,直到研究人员在2009年的演示中证明他如何使用他的网站的叶子证书为大型电子商务网站打造有效的证书。

8. 验证秘钥用法

“密钥用法”扩展说明了证书中包含的密钥的用途。此类目的的示例包括加密,签名,证书签名等。浏览器拒绝违反其密钥使用限制的证书,例如遇到具有仅用于CRL签名的密钥的服务器证书。

9. 浏览器继续处理剩余的关键扩展

在检查完上述的所有项以后,浏览器继续验证当前证书指定为关键的所有剩余扩展,然后再继续下一步。如果浏览器无错误地到达路径的叶证书,则该路径被接受为有效。如果产生任何错误,则路径被标记为无效,并且建立安全连接失败。

总结

一篇下来,发现可以深挖的点太多了,但是这些步骤上的关系就足以看懵了。