# HTTPS 介绍

HTTPS 并不是一个新协议,而是 HTTP+SSL(TLS)。原本 HTTP 先和 TCP(假定传输层是 TCP 协议)直接通信,而加了 SSL 后,就变成 HTTP 先和 SSL 通信,再由 SSL 和 TCP 通信,相当于 SSL 被嵌在了 HTTP 和 TCP 之间。

而在整个 HTTPS 流程中,用到了两种加密方式:对称加密和非对称加密。

这是因为非对称加密的效率远不如对称加密,因此通常是用非对称加密来加密对称加密的密钥。

使用对称加密来加密真正的 http 数据。

image-20220401135729951

# 抓包分析(单向认证)

SSL 主要的作用就是用来协商通信双方的安全参数,然后基于协商的安全参数进行安全通信。所以首当其冲地,第一个要解决的问题就是如何进行密钥交换。考虑到对称密码和非对称密码的性能差异显著,在实际使用中往往使用对称密码对数据进行加密,而使用非对称密码来完成重要的密钥交换和身份认证。

SSL 协议分为两个阶段:握手阶段和应用阶段。握手阶段主要负责协商安全参数,应用阶段则基于前面协商的安全参数进行数据通信。

# 整体报文

可以看到,一个整体的报文流程如下,从 588-598 是一个较完整的过程。

但我们先从 560-572 分析,可以看到,560-562 这三个包,很明显是一个简单的 tcp 三次握手判断存活,然后才开始密钥交换,但明显在这个会话中,握手是没成功的(服务端证书未通过浏览器校验)

接着我在浏览器端选择信任证书后,就开始了第二次 TLS 握手,即 588-598 这段,从中我们大致可以看到,如下几个部分:

​ ①TCP 三次握手(判断存活,部署于 TLS 握手协议的内容)

​ ②Client Hellow

​ ③ Server Hellow,Certificate ,Server Key Exchange、Server Hello Done

​ ④Client Key Exchange、Change Cipher Spec、Encrypted Handshake Message

​ ⑤New Session Ticket、、Change Cipher Spec、Encrypted Handshake Message

​ ⑥Application Data

下面我们就详细介绍这几个部分的消息是干嘛的

image-20220401135951885

注:上面的流程是单向认证(服务端没有验证客户端的身份),如果服务端也需要验客户端的身份,会在第一次交互中发送 Certificate Request 消息,客户端相应的在第二次交互中发送自己的 Certificate 以及 CertificateVerify 消息给服务端。

PS:这里简单的提一下浏览器是如何验证证书的合法性

https://www.zhihu.com/question/37370216

从上面的 Certificate 包中,浏览器就得到了证书的一些信息,然后会按照如下流程来对证书进行校验,若合法则开始密钥协商交换。否则中断当前的会话。

img

CA 签发证书的过程,如上图左边部分:

  • 首先 CA 会把持有者的公钥、用途、颁发者、有效时间等信息打成一个包,然后对这些信息进行 Hash 计算,得到一个 Hash 值;
  • 然后 CA 会使用自己的私钥将该 Hash 值加密,生成 Certificate Signature,也就是 CA 对证书做了签名;
  • 最后将 Certificate Signature 添加在文件证书上,形成数字证书;

客户端校验服务端的数字证书的过程,如上图右边部分:

  • 首先客户端会使用同样的 Hash 算法获取该证书的 Hash 值 H1;
  • 通常浏览器和操作系统中集成了 CA 的公钥信息(浏览器预存的一些 CA 的公钥)

# Client Hellow (客户端发送)

Client 和 Server 建立连接的时候,Client 首先会先发送 Client Hello 问候消息,主要是发送客户端所支持的 SSL/TLS 最高协议版本号和所支持的加密算法集合及压缩方法集合等信息给服务器端。

如下图:

image-20220401141845311

其中加密套件较为重要:这里简单介绍,比如 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,密钥协商算法是 ECDHE(短暂椭圆曲线),身份认证算法是 RSA,对称加密算法是 AES_128_GCM,消息摘要算法是 SHA256。

# Server Hellow (服务端返回)

服务端收到了客户端的 Hello,通过客户端的配置信息,结合服务端的自身情况,给出了最终的配置信息。

以客户端支持的优秀,但是在 web 服务器中可以设置以服务端优先(避免 TLS 降级攻击)。

image-20220401150027032

PS: 这里服务器选择的密码套件很关键,这关系着我们能否解密流量。

# Server Certificate(服务端返回)

服务端下发证书,让客户端验证服务端的身份,包含后面用于加密预主密钥的的公钥(由前面 ServerHellow 选择的加密套件决定,临时的密钥交换协议则不用这个公钥去加密预主密钥)。

image-20220401142857254

# Server Key Exchange(服务端返回)

根据 Server Hellow 选择的算法,如果选择的是临时的密钥交换协议,那么就会发送该消息,以便双方协商参数,生成预主密钥。

这里服务器会生成一对临时的公私钥 。需要注意的是 DHE_DSS、DHE_RSA、DH_anon 算法会发送此消息。TLS_RSA、DH_DSS、DH_RSA 算法不会发送此消息。

image-20220401143537716

# Server Hello Done(服务端返回)

当 Server 发送完问候和相关消息,而且这些消息足够支持密钥交换,紧接着 Server 会发送一条 Server Hello Done 消息。
发送完成后,Server 会等待 Client 响应,Client 收到消息后,先验证 Server Certificate 证书链,再继续进行 Client 的密钥交换。

image-20220401143806891

# Client Key Exchange(客户端发送)

Client Key Exchange 将作为 Server Hello Done 之后的第一条消息(单向认证的情况下)。
通过此消息,可以直接交换 premaster secret,或者交换 DH 的协商参数。

客户端随机生成 46 位的随机数 + 2 位的 client_version, 加密后发送给服务端。服务端接收到后能通过私钥进行解密得预主密钥。

image-20220401150224122

# Change Cipher Spec(客户端发送)

告诉服务器我这边已经完成了密钥交换了,接下来该进入密钥检查环节了。

image-20220401145550578

# Encrypted Handshake Message(客户端发送)

这里就是客户端的 Client Finished 消息。也是整个 SSL 过程中,发送给服务端的第一个加密消息。待后面服务端接收后,服务端用同样的方式计算出已交互的握手消息的摘要,与用主密钥解密后的消息进行对比,一致的话,说明两端生成的主密钥一致,完成了密钥交换。

PS:这个 Encrypted handshake message 就是把当前(准备发送 Encrypted handshake message)前,自己收到的数据和发送的数据进行一次简单运算(hash + 对称加密),一方面能够防止数据被篡改,一方面用来确认密钥的准确性。

image-20220401150629000

# New Session Ticket、Change Cipher Spec、Encrypted Handshake Message (服务端发送)

①服务器告诉客户端一个会话时间,用处就是在一段时间之内(超时时间到来之前),双方都以刚刚交换的密钥进行通信,超过不通信就握手失败。

②服务端通知服务端,后续的报文将会被加密。

③和上面的客户端的 Encrypted Handshake Message 一样,是服务端发出的第一条加密信息。客户端按照协商好的主密钥解密并验证正确后,SSL 握手阶段完成。

image-20220401150818545

# Application Data

应用数据传输消息。因为这里是 HTTPS,所以可以对 HTTP 应用协议数据加密然后传输了。并且从这里,无法知道密钥是什么,也无法知道这里传输的是什么数据。

image-20220401151058222

# 小结

①对称加密的密钥是由客户端生成的
②这个密钥经过了服务端提供的公钥进行加密,也就是说只有服务端的私钥能够解密获取正确的密钥。(客户端缓存中也有)
③SSL 证书在这个过程中起了两个作用:身份验证与数据加密(在实际的过程中,通常证书私钥的功能被削弱到只用来做身份认证)。浏览器通过预存 CA 公钥判断证书合法性,而数据加密则是要看具体情况了。单纯使用 RSA 算法时,RSA 算法既用来验证服务器的身份,也用来加密预主密钥。单纯采用 DH 算法时,DH 算法只用来加密预主密钥,没办法验证服务器身份,称为 anonymous DH。DH 算法还可以跟 RSA 算法一起使用,RSA 验证服务器身份,DH 算法加密预主密钥。而上面的抓包中,证书的公钥就没被用来加密预主密钥。

# 思考:我们什么情况下能用私钥去破解 TLS 加密的数据

这里先给结论:有 Server Key Exchange 个包就做不到证书私钥破解数据

在上面过程中决定着我们能否解包一个关键地方在于服务端选择的加密套件是什么?如果使用临时的密钥交换协议,那么使用的并不是证书的公私钥,也自然没办法破解数据。

而 Server Key Exchange 这个包就是服务器发给客户端的临时公钥,因此判断是否存在 Server Key Exchange 这个包就能知道这个包的数据能否使用证书的私钥去破解。

因此我们比较关注以下问题:


Q:什么时候才使用证书的公钥去加密对称加密密钥?或者说什么时候才不发送Server Key Exchange这个值?

A:对于使用非DHE/ECDHE非对称密钥协商算法的SSL握手将不会发送Server Key Exchange。也就是说DHE/ECDHE使用的是临时密钥,证书公私钥不起数据加密作用。
Q:什么是DH和ECDH,加个E又是什么情况?

A: DH即Diffie Hellman密钥协商算法,而ECDH则是椭圆曲线密钥协商算法,是ECC(椭圆曲线)和DH算法的结合。
DHE和ECDHE多了个E即Elliptic Curve Diffie-Hellman Exchange Ephemeral,短暂的(椭圆曲线)密钥协商算法。多了一个Ephemeral(短暂的),即密钥是短暂的,每次握手都会协商出一个预主密钥,和RSA、DH、ECDH不同:

 • RSA,证书公钥、私钥直接参与密钥交换,私钥泄漏,存在向前攻击问题。

 • DH、ECDH,证书公钥、私钥参与协商,对于Client,证书公钥作为随机数X1。对于Server,证书私钥作为随机数X2。

 • DHE、ECDHE,证书公钥、私钥不参与协商,每次握手都会计算随机数X。

很显然,这几种协商算法中,ECDHE是最安全的,即便当前会话的密钥泄漏了,也不影响之前的会话,是前向安全的。所以现在基本都是使用ECDHE算法。
Q:什么样的证书才会使用自己的私钥,而不是临时私钥?

A:根据RFC标准中的描述, 如果服务器证书包含Diffie Hellman公钥,则使用证书的私钥。但是事实上,服务器对于加密套件有着自己的权重算法,除非是没得选的情况下,不然不会轻易使用RSA和ECDH算法。

image-20220401152026153