HTTPS:浏览器如何验证数字证书?

2,565 阅读5分钟

前言

在前面的文章 HTTPS:让数据传输更安全 中,我们聊了下面几个问题:

  • HTTPS 使用了对称和非对称的混合加密方式,这解决了数据传输安全的问题。
  • HTTPS 引入了中间机构 CA,CA 通过给服务器颁发数字证书,解决了浏览器对服务器的信任问题。

关于 “浏览器如何验证数字证书” 这个问题我们并没有展开介绍,今天我们就来聊一聊这个问题。

数字证书申请流程

比如用户需要向 CA 机构申请数字证书,流程是什么样的呢?

  • 首先用户需要填写了一张含有自己身份信息的表单,身份信息包括了自己公钥、站点资料、公司资料等信息,然后将其提交给了 CA 机构。
  • CA 机构会审核表单中内容的真实性。
  • 审核通过后,CA 机构会拿出自己的私钥,对表单的内容进行一连串操作,包括了对明文资料进行 Hash 计算得出信息摘要。
  • 再利用 CA 的私钥加密信息摘要得出数字签名。
  • 最后将数字签名也写在表单上,并将其返还给用户,这样就完成了一次数字证书的申请操作。

大致流程你可以参考下图:

浏览器验证证书的流程

在浏览器和服务器建立 HTTPS 链接的过程中,浏览器首先会向服务器请求数字证书,之后浏览器要做的第一件事就是验证数字证书。具体地讲,浏览器需要验证证书的有效期、证书是否被 CA 吊销、证书是否是合法的 CA 机构颁发的。

数字证书和身份证一样也是有时间期限的,所以第一部分就是验证证书的有效期;有时候有些数字证书被 CA 吊销了,吊销之后的证书是无法使用的,所以第二部分就是验证数字证书是否被吊销了;最后还要验证数字证书是否是 CA 机构颁发的,验证的流程如下:

  • 首先,浏览器利用证书的原始信息计算出信息摘要。
  • 然后,利用 CA 的公钥来解密数字证书中的数字签名,解密出来的数据也是信息摘要。
  • 最后,判断这两个信息摘要是否相等就可以了。

不过这又带来了一个新的疑问:浏览器是怎么获取到 CA 公钥的?

浏览器是怎么获取到 CA 公钥的?

通常,当你部署 HTTP 服务器的时候,除了部署当前的数字证书之外,还需要部署 CA 机构的数字证书,CA 机构的数字证书包括了 CA 的公钥,以及 CA 机构的一些基础信息。

然后在建立 HTTPS 链接时,服务器会将这两个证书一同发送给浏览器,于是浏览器就可以获取到 CA 的公钥了。

解决了获取 CA 公钥的问题,新的问题又来了,如果这个证书是一个恶意的 CA 机构颁发的怎么办?所以我们还需要浏览器证明这个 CA 机构是个合法的机构。

证明 CA 机构的合法性

这里并没有一个非常好的方法来证明 CA 的合法性,妥协的方案是,直接在操作系统中内置这些 CA 机构的数字证书。

将所有 CA 机构的数字证书都内置在操作系统中,这样当需要使用某 CA 机构的公钥时,我们只需要依据 CA 机构名称,就能查询到对应的数字证书了,然后再从数字证书中取出公钥。

不过这种方式依然存在问题,因为在实际情况下 CA 机构众多,因此操作系统不可能将每家 CA 的数字证书都内置进操作系统。

数字证书链

于是人们又想出来一个折中的方案,将颁发证书的机构划分为两种类型,根 CA 和中间 CA,通常申请者都是向中间 CA 去申请证书的,而根 CA 作用就是给中间 CA 做认证,一个根 CA 会认证很多中间的 CA,而这些中间 CA 又可以去认证其他的中间 CA。因此,每个根 CA 机构都维护了一个树状结构,一个根 CA 下面包含多个中间 CA,而中间 CA 又可以包含多个中间 CA。这样就形成了一个证书链,你可以沿着证书链从用户证书追溯到根证书。

到了这里,依然存在一个问题,那就是浏览器怎么证明根证书是合法的?

如何验证根证书的合法性?

其实浏览器的判断策略很简单,它只是简单地判断这个根证书在不在操作系统里面,如果在,那么浏览器就认为这个根证书是合法的;如果不在,那么就是非法的。

如果某个机构想要成为根 CA,并让它的根证书内置到操作系统中,那么这个机构首先要通过 WebTrust 国际安全审计认证。

目前通过 WebTrust 认证的根 CA 有 Comodo、geotrust、rapidssl、symantec、thawte、digicert 等。也就是说,这些根 CA 机构的根证书都内置在各大操作系统中,只要能从数字证书链往上追溯到这几个根证书,浏览器就会认为使用者的证书是合法的。