HTTPS Handshake

1. 客户端发出请求(ClientHello)

客户端(通常是浏览器)先向服务器发出加密通信的请求,这被叫做 ClientHello 请求。在这一步,客户端主要向服务器提供以下信息。

    1. 支持的协议版本,比如TLS 1.0版。
    1. 一个客户端生成的随机数,稍后用于生成”对话密钥”。
    1. 支持的加密方法,比如RSA公钥加密。
    1. 支持的压缩方法。

这里需要注意的是,客户端发送的信息之中不包括服务器的域名。也就是说,理论上服务器只能包含一个网站,否则会分不清应该向客户端提供哪一个网站的数字证书。这就是为什么通常一台服务器只能有一张数字证书的原因。对于虚拟主机的用户来说,这当然很不方便。2006年,TLS协议加入了一个 Server Name Indication 扩展,允许客户端向服务器提供它所请求的域名。

2. 服务器回应(SeverHello)

服务器收到客户端请求后,向客户端发出回应,这叫做 SeverHello。服务器的回应包含以下内容。

  • 确认使用的加密通信协议版本,比如TLS 1.0版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信。
  • 一个服务器生成的随机数,稍后用于生成”对话密钥”。
  • 确认使用的加密方法,比如RSA公钥加密。
  • 服务器证书。

除了上面这些信息,如果服务器需要确认客户端的身份,就会再包含一项请求,要求客户端提供”客户端证书”。比如,金融机构往往只允许认证客户连入自己的网络,就会向正式客户提供USB密钥,里面就包含了一张客户端证书。

3. 客户端回应

客户端收到服务器回应以后,首先验证服务器证书。如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。如果证书没有问题,客户端就会从证书中取出服务器的公钥。然后,向服务器发送下面三项信息。

  • 一个随机数。该随机数用服务器公钥加密,防止被窃听。
  • 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
  • 客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验。

上面第一项的随机数,是整个握手阶段出现的第三个随机数,又称 pre master key。有了它以后,客户端和服务器就同时有了三个随机数,接着双方就用事先商定的加密方法,各自生成本次会话所用的同一把”会话密钥”。

需要用三个随机数来生成”会话密钥”的原因如下

  1. 不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于SSL协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。
  2. 对于RSA密钥交换算法来说,pre master key 本身就是一个随机数,再加上 hello 消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥。
  3. pre master key 的存在在于SSL协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么 pre master key 就有可能被猜出来,那么仅仅用 pre master key 作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上 pre master key 三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了。

此外,如果前一步,服务器要求客户端证书,客户端会在这一步发送证书及相关信息。

4. 服务器的最后回应

服务器收到客户端的用公鑰加密的第三个随机数 pre master key 之后,會使用自己的私钥,解密並获取這個随机数。计算生成本次会话所用的”会话密钥”。然后,向客户端最后发送下面信息

  1. 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
  2. 服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供客户端校验。

至此,整个握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的HTTP协议,只不过用”会话密钥”加密内容。

注意服务器的公钥和私钥在整個過程中只使用過一次,即用于加密和解密”对话密钥”(非对称加密),无其他作用。

某些客户(比如银行)想要使用外部CDN,加快自家网站的访问速度,但是出于安全考虑,不能把私钥交给CDN服务商。这时,完全可以把私钥留在自家服务器,只用来解密对话密钥,其他步骤都让CDN服务商去完成。