一文看懂 HTTPS 握手过程

1,302 阅读8分钟

我正在参加「掘金·启航计划」

HTTPS 是什么

Hypertext Transfer Protocol Secure (HTTPS) is an extension of the Hypertext Transfer Protocol (HTTP). It uses encryption for secure communication over a computer network, and is widely used on the Internet.[1][2] In HTTPS, the communication protocol is encrypted using Transport Layer Security (TLS) or, formerly, Secure Sockets Layer (SSL). The protocol is therefore also referred to as HTTP over TLS,[3] or HTTP over SSL.

以上是 HTTPS 在维基百科的定义,简单概括就是:“HTTPS 是对 HTTP 的扩展,其使用加密技术在计算机网络上进行安全通信,并在互联网上有广泛的应用。在 HTTPS 中,通信协议使用的是 TLS 或早期的 SSL。所以 HTTPS 也被称为 TLSSSL 之上的 HTTP”。

TLSSSL 之上的 HTTP”,是否说明了 HTTP"S" 是独立分开的?确实是的,HTTPSHTTP 负责传输,"S" 负责安全。而这个 "S" 新版本叫 TLS,老版本叫 SSL

SSL/TLS 简单发展历程

SSL(Secure Sockets Layer) 是网景公司(Netscape)设计的主要用于Web的安全传输协议,这种协议在Web上获得了广泛的应用。 基础算法由作为网景公司的首席科学家塔希尔·盖莫尔(Taher Elgamal)编写,所以他被人称为“SSL之父”。

  • 1994年,NetScape公司设计了SSL协议(Secure Sockets Layer)的1.0版,但是未发布。
  • 1995年,NetScape公司发布SSL 2.0版,很快发现有严重漏洞。
  • 1996年,SSL 3.0版问世,得到大规模应用
  • 1999年,互联网标准化组织ISOC接替NetScape公司,发布了SSL的升级版 TLS (Transport Layer Security) 1.0版。
  • 2006年4月,IETF发布TLS 1.1版本(RFC4346),包含一些小的安全改进。2008年8月,TLS 1.2版本(RFC5246)发布,移除了老旧加密套件,增强了协议的安全性,TLS 1.2协议是目前主流的TLS协议版本。
  • 2018年3月,TLS 1.3协议正式批准问世,成为了新一代TLS协议版本。TLS 1.3版本历经长达4年28次草案修改,是迄今为止改动最大的一次,既能提高互联网用户的访问速度,又能增强安全性,大大提升HTTPS连接的速度性能,用户的使用体验度得到明显的提升。

所以HTTPS本质上就是HTTP+TLS,其安全通信是靠 TLS(指 SSL/TLS)来完成的。它们的工作流程简单来说是:利用非对称加密协商一个对称加密密钥,再用这个密钥在每次通信时加解密。 关键词加密、解密,那我们就先来看看HTTPS用到了哪些加密技术。什么是对称、非对称加密?Hash是加密么?如果不了解加密的,一定要看,理解加密对于理解 HTTPS 握手过程非常重要,如果已经了解可以跳过。

在了解加密、Hash 之后我们来看看 HTTPS 是如何用这些技术手段工作的。

HTTPS 握手

image.png 这是一个最常规的握手流程,不需要验证客户端身份但需要验证服务端身份,也叫单向认证。

image.png 上图是Wire Shark工具抓包的握手信息,下面我们来通过这张图详细聊聊这个握手的过程,把步骤一步步拆解。

Client Hello

Client Hello 是 TLS 握手的第一个步骤,不是指客户端向服务端发送了一个Client Hello字符串,而是这个步骤的名称叫作Client Hello,包括后面的 Server Hello等等都是步骤的名称。Client Hello表示客户端向服务端发起了一个TLS握手请求,那我们来看看这个请求发送了哪些信息。

image.png

可以看到 Client Hello 后面有个 1 ,这其实就是客户端发给服务端的实际值。服务端收到这个1就知道客户端发起了TLS链接请求。此外除了Client Hello,本次报文内容主要还包括以下信息:

  • 支持的TLS版本 把客户端支持的最佳TLS版本告知服务端,服务端选择一个支持的版本
  • 支持的加密套件类型(Cipher suite) 客户端支持的加密套件列表,按优先级顺序排列(对称、非对称加密、Hash,不了解这些可以先阅读什么是对称、非对称加密?Hash是加密么?,不了解的同学一定要看,非常重要!!!)
  • 客户端随机数 ,每次握手的随机数都不一样,这个随机数也会在客户端保存,用来生成密钥

这些就是Client Hello的主要内容,主要向客户端发送其支持的工具种类和随机数。

Server Hello

image.png

服务端在收到Client Hello之后,发送的内容结构跟Client Hello对应,会向客户端发送选择的TLS版本加密套件类型,同时还有客户端随机数。现在,客户端与服务端就都有了基础共同信息。

Certificate

image.png 这一步还是服务端向客户端发消息,Certificate(不了解证书的同学,可以看这篇文章HTTPS 用到的数字证书是怎么一回事? - 掘金 (juejin.cn)) 消息用于携带服务器 X.509 证书链,目的是让客户端校验服务端身份。

Server Key Exchange

image.png ServerKeyExchange 是可选的,消息内容对于不同的协商算法套件会存在差异。部分场景下,比如使用 RSA 算法时,服务器不需要发送此消息。

此处基于 DH 算法的握手,需要单独发送一条 ServerKeyExchange 消息带上Server Params,这是 DH 算法所需参数,用于协商密钥

Server Hello Done

这一步是服务端向客户端发送一个单字节数据,表示已将所有预计的握手信息发送完毕,后面将等待客户端发送消息。

Verify Certificate

客户端验证服务端发来的证书信息,验证通过才会继续通信,否则中断或提示,具体验证信息如下:

  • 证书链的可信性
  • 证书是否被吊销
  • 证书有效期
  • 证书主机名是否与请求主机名一致 验证大致过程:先读取证书明文信息,根据对应散列函数获取摘要信息;利用公钥解密相关签名信息得到摘要,对比两个摘要,如果信息一致则整数合法;再去查询证书其他信息

Client Key Exchange

证书验证通过之后,客户端会生成预主密钥pre-master,不过会因不同的密钥协商算法而有差异:

  • 如果是 ECDHE 算法,会根据服务端 ECDHE 参数服务端 ECDHE 参数计算出一个主密钥pre-master
  • 如果是 RSA 算法,则用随机算法生成pre-master,

怎么把这个pre-master给服务端也会因协商密钥的算法而有差异。

image.png 此处使用的是 ECDHE 算法,ClientKeyExchange传递的是算法的客户端参数,如果使用的是 RSA 算法则此处应该传递用公钥对pre-master加密后的密文。

此时客户端有client-randomserver-randompre-master三个随机数,然后会根据这三个参数生成master-secret,再根据master-secret生成了

  • client encryption key
  • server encryption key
  • client MAC key
  • server MAC key

encryption key是对称加密密钥,服务端客户端用各自的密钥加解密;MAC是 Message Authenticate Code (TLS 使用 HMAC)的缩写,它是一个数字签名,用来验证数据的完整性,可以检测到数据是否被篡改。

Change Cipher Spec、

通知服务端后续的消息都采用协商的通信密钥和加密算法进行加密通信,发送一个单字节数据

Finished

image.png 这一步客户端会将前面握手步骤的信息结合到一起,再用client MAC key生成MAC,再用刚刚产生的client encyption key加密,,发送到服务端。

Server Verify

根据握手算法,如果是RSA算法就用私钥解密获取到pre-master;如果是DH算法就结合DH Client Params计算出 pre-master。然后跟客户端一样,得到master-secret生成了,再生成与客户端相同的四个密钥。

密钥生成之后,用client encryption keyMAC key 校验客户端发过来的 Encrypted HandShake Message.

Change Cipher Spec、Finish.

这两步对应客户端的操作,是一样的,这边就不重复了。主要就是客户端验证服务端的加密后的握手消息。

握手结束

经过以上的步骤,握手过程就结束了,下面就可以用约定的密钥进行加密通信了。 应用数据在传输之前,首先要附加上MAC key,然后再对这个数据包使用encryption key进行加密。在服务端收到密文之后,使用client encryption key进行解密,客户端收到服务端的数据之后使用server encryption key进行解密,然后使用各自的MAC key对数据的完整性包括是否被篡改进行验证。

一段话总结握手过程

TLS客户端(也是TCP的客户端)在TCP链接建立之后,发出一个ClientHello来发起握手,这个消息里面包含了自己可实现的算法列表和其它一些需要的消息,TLS的服务器端会回应一个ServerHello,这里面确定了这次通信所需要的算法,然后发过去自己的证书(里面包含了身份和自己的公钥)。Client在收到这个消息后会生成一个pre-master,用TLS服务器的公钥加密后传过去(或「DH算法」计算出),TLS服务器端用自己的私钥解密后(或「DH算法」计算出),会话密钥协商成功,双方可以用同一份会话密钥来通信了。