September 13, 2017

TLS握手过程

最近和朋友吃饭的时候,聊到了HTTPS,HTTPS其实就是基于TLS建立了安全信道的HTTP协议。所以可以说,HTTPS最重要的就是TLS的握手过程。这篇post整理了一下TLS的握手过程。

前置知识

这里要先讲几个概念,在后面对于TLS握手过程的描述中会用到这几个概念。

HTTPS TLS和SSL的关系

SSL是90年代Netscape弄出来的一套东西,为的是解决HTTP协议明文传输数据的问题。后来SSL慢慢成了事实上的标准,于是IETF就把SSL标准化了,名字叫做TLS,TLS 1.0其实就是SSL 3.1。所以SSL和TLS经常被放在一起写成SSL/TLS,因为这两个名词在现在其实就是同一个东西。HTTPS是使用TLS的HTTP协议。

证书及信任链

我们知道,HTTPS的网站都有一个自己的证书,用于表明自己的身份。证书本质上是为了让公钥能可信的传输。公钥是放在证书里面的,如果证书可信,那么公钥就也是可信的。那为什么一个公钥是可信的呢?这就要说到信任链和CA。CA指的是Certificate Authority,CA都是权威机构,他们的证书叫做根证书,这些根证书被操作系统信任,根证书信任的证书也是可信的。因此权威机构颁发的证书都能被操作系统信任,这就组成了信任链。

TLS握手过程

这里借用了一张CloudFlare的图,这张图不是很详细,但我个人觉得这个粒度应该是最合适的,主要部分都有描述,又不至于让人过于纠结细节。
SSL handshake
其实TLS提供了多种密钥交换算法,这里以RSA为例,分步讲解以下TLS的握手过程。

客户端初始请求

客户端向服务器发出请求,会带上以下信息:

  1. 一个客户端生成的随机数
  2. 支持的加密方式,即图中的Cipher Suite
  3. 支持SSL/TLS协议的版本号
  4. Session ID,如果是之前断开的会话,会带上Session ID用来恢复会话。
  5. 签名使用的哈希算法
服务器回应

服务器响应客户端的请求,如果上一步带上了Session ID,则直接恢复会话,否则带上以下信息给客户端:

  1. 选择SSL/TLS协议版本号
  2. 选择加密方式
  3. 一个服务器生成的随机数
  4. 服务器证书

客户端会在这里校验服务器证书的合法性,包括检测证书有效时间,以及证书中域名与当前会话域名是否匹配,并沿着信任链查找顶层证书颁发者是否是操作系统信任的CA机构,这里验证信任链的时候,需要用上一级证书的公钥对证书里的签名进行解密,还原对应的摘要值,再使用证书信息计算证书的摘要值,最后通过对比两个摘要值是否相等,如果不相等则认为该证书不可信,如果相等则认为该级证书链正确,以此类推对整个证书链进行校验。

客户端回应

客户端校验服务器证书的合法性,生成premaster secret,向服务器发送以下信息:

  1. 用服务器证书取出的公钥加密后的premaster secret,这里的premaster secret其实是另一个随机数
  2. 加密约定改变通知,通知服务器,以后的通信都适用协商好的加密方法和密钥进行加密
  3. 客户端握手结束通知。这个报文也是验证消息,是前面发送的所有内容的哈希值,用来供服务器校验。
服务器最后确认

这是握手过程的最后一步,服务器会把以下信息发送给客户端:

  1. 加密约定改变通知,通知客户端,以后的通信都适用协商好的加密方法和密钥进行加密
  2. 服务器握手结束通知,该报文也作为校验消息,供客户端验证。

到这个时候,客户端和服务器同时拥有了3个随机数,使用这三个随机数生成的密钥,将被用于后续通信的对称加密。也就是说,只有握手过程才有非对称加密,非对称加密是比较慢的,因此只用于建立安全的信道,Payload的传输都是对称加密的,对称加密的速度和资源占用比非对称加密都要好,因此对性能的影响是很小的。