信任始于握手 — TLS 1.2 连接过程详解

网络安全篇,面对复杂多变的网络环境,我们需要掌握哪些关于网络安全的相关知识,聊一聊与网络安全相关的:HTTPS、SSL、TLS 等。


网络安全专题
  • 网络安全的基石

《网络安全 — HTTPS》
《网络安全的基石(上)— 加密》
《网络安全的基石(下)— 完整性与身份认证》
《公钥信任问题 — 数字证书与 CA》
《信任始于握手 — TLS 连接过程详解》

  • HTTPS 的优化

《TLS 1.3 特性解析》
《如何优化 HTTPS 连接》- 待完善


TLS 协议的组成

在介绍 TLS 握手之前,我们先来简单介绍下 TLS 协议的组成。

TLS 实际由若干不同职责的模块组成,比较常用的有握手协议变更密码规范协议警报协议记录协议等。

从体系结构图可以看出,SSL/TLS 协议可分为两层:握手协议记录协议

握手协议

握手协议用来协商会话参数(如会话密钥、应用层协议等)。它实际由若干不同职责的子模块组成,比较常用的有握手协议变更密码规范协议警报协议记录协议等。

  • 握手协议(Handshake Protocol)

建立在 SSL 记录协议之上,是 TLS 里最复杂的子协议,要比 TCP 的 SYN/ACK 复杂的多。用于在实际传输数据之前,通讯双方进行身份认证、协商加密算法、交换会话密钥,用于后续的混合加密系统。

  • 变更密码规范协议(Change Cipher Spec Protocol)

是一个非常简单的“通知”。用于告诉对方,后续的数据都将使用加密保护。那么反过来,在它之前,数据都是明文的。为了保障 SSL 传输过程的安全,客户端和服务器双方应该每间隔一段时间改变加密规范。在客户端和服务器完成握手协议之后,它需要向对方发送相关消息,通知对方随后的数据将使用已协商的加密规范进行保护。

  • 警报协议(Alert Protocol)

职责是向对方发出警报信息,类似于 HTTP 协议里的状态码。比如 protocol_version 就是不支持旧版本,bad_certificate 就是证书有问题,收到警报后另一方可以选择继续,也可以立即终止连接。警报协议(Alert Protocol)的职责是向对方发出警报信息,类似于 HTTP 协议里的状态码。比如 protocol_version 就是不支持旧版本,bad_certificate 就是证书有问题,收到警报后另一方可以选择继续,也可以立即终止连接。

记录协议 (Record Protocol)

建立在可靠的传输协议(如 TCP)之上,为高层协议提供数据封装、压缩及加密等基本功能的支持。保证连接的机密性完整性。所有的其他子协议都需要通过记录协议发出。但多个记录数据可以在一个 TCP 包里一次性发出,也并不需要像 TCP 那样返回 ACK。

有关 SSL 协议体系结构的更详细介绍你可以参考这篇文章。

SSL/TLS 在网络模型中的位置

你是否有想过?在网络通信模型中, TLS 协议是处在什么位置呢?下面我们通过一张图来简单了解下:

SSL/TLS 在网络模型中属于应用层协议(实际在 OSI 的会话层),接管应用层的数据加解密,并通过网络层进行收发。


TLS 握手过程

下图简要描述了 TLS 的握手过程,其中每个“框”都是一个记录,多个记录组成一个 TCP 包发送。所以,最多要经过 2 RTT(4 个消息)才可以完成握手,然后就可以在安全的通信环境里发送 HTTP 报文,实现 HTTPS 协议。

TLS 握手总是以 ClientHello 消息开始,就跟 TCP 握手总是以 SYN 包开始一样。


上面是相对简要的握手过程,实际上关于 TLS 握手过程可以划分为两种方式:使用 RSA 做密钥交换和 ECDHE 做密钥交换。下面我们就详细地介绍下它们的握手过程。

ECDHE 握手

在 TCP 成功建立连接之后,客户端首先发送一个 “Client Hello” 消息,也就是跟服务器“打招呼”。

内容包括:客户端的版本号、支持的密码套件,还有一个随机数(Client Random),用于后续生成会话密钥。

Handleshake Protocol: Client Hello
              Version: TLS 1.2(0x0303)
              Random:1cbf803321fd26234ds78sleds...
              Cipher Suites(17 suites)
                        Cipher Suite:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f) 
                        Cipher Suite:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
                        ...

可以看到 Client Hello 消息携带的相关信息,关键的随机数需要保留着

作为“礼尚往来”,服务器收到 “Client Hello” 后,会返回一个 “Server Hello” 消息。把 TLS 版本对一下,也会返回一个随机数(Server Random),然后从客户端的列表里选一个作为本次通信使用的密码套件,如下选择了 “TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384”。

Handshake Protocol: Server Hello
            Version: TLS 1.2(0x0303)
            Random: 0e6320f21bae50842e96…
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)

这个意思是:把版本好对上了,服务端在客户端支持的密码套件中选择了一个合适的:椭圆曲线 + RSA、AES、SHA384。服务端也返回一个随机数,需要客户端保留着

然后,服务端为了证明自己的身份,就把证书也发给客户端(Server Certificate 消息)。

接下来的关键操作,因为服务器选择了 ECDHE 算法,所以它会在证书发送后发送 “Server Key Exchange” 消息,里面是椭圆曲线的公钥(Server Params),用来实现秘钥交换算法,再加上自己的私钥签名认证。

Handshake Protocol: Server Key Exchange
            EC Diffie-Hellman Server Params
                Curve Type: named_cure (0x03)
                Named Curve: x25519 (0x001d)
                Pubkey: 3b39deaf00217894e...
                Signature Algorithm: rea_pkcs1_sha512 (0x0601)
                Signature: 37141adac38ea4...

这一步相当于:服务端又给了一个算法参数,和刚才的随机数一样需要客户端保留,为了防止别人冒充,服务端用私钥进行签名。

之后的 “Server Hello Done” 消息,服务端的“打招呼”完毕。

此时第一个 RTT 就结束了(2 个 TCP 数据包),结果是客户端和服务器通过明文共享了三个信息:Client RandomServer RandomServer Params

客户端也拿到了服务器的证书,那这个证书里的公钥是否真实有效呢?回想下我们在上期《公钥信任问题 — 数字证书与 CA》介绍的证书验证过程,确认证书的真实性,再用证书公钥验证签名,就确认了服务器的身份。

然后,客户端按照密码套件的要求,也生成一个椭圆曲线的公钥(Client Params),用 “Client Key Exchange” 消息发给服务器。

Handshake Protocol: Client Key Exchange
              EC Diffie-Hellman Client Params
              Pubkey: 8c674d0e08dc27b5eaa…

现在客户端和服务器都拿到了密钥交换算法的两个参数(Client Params、Server Params),就用 ECDHE 算法生成一个 “Pre-Master(预主密钥,其实也是个随机数)”。

具体的计算过程和原理非常复杂,该计算能够保证即使黑客截获了之前的参数,也是绝对算不出这个随机数的。具体你可参考这篇介绍。

现在客户端和服务器有了三个随机数:Client RandomServer RandomPre-Master(预主密钥)。然后通过它们生成加密会话的主密钥 “Master-Secret”。由于黑客拿不到 “Pre-Master”,所以也就得不到主密钥。

TLS 的设计考虑的非常全面,为了保证真正的“完全随机和不可预测”,他们不信任客户端或服务器的伪随机数的可靠性,所以采用三个不可靠的随机数混合起来,那么“随机”的程度就非常高了,足够让黑客难以猜测。

生成的主密钥为 48 字节,但它还不是最终用于通信的会话密钥,还会再用主密钥派生出会话密钥。到这一步 TLS 的握手就要结束了。客户端发送一个 “Change Cipher Spec”,然后再发一个 “Finished” 消息,把之前所有发送的数据做个摘要,再加密一下,让服务器做个验证。

服务器也是同样的操作,发送 “Change Cipher” 和 “Finished” 消息,双方验证加密解密 OK,握手正式结束,后面就开始收发被加密的 HTTP(Application Data)请求和响应了。

RSA 握手过程

如今主流的 TLS 握手就是 ECDHE,整个过程可以说是够复杂的。不过整个握手过程好像和其他的地方看到的不一样呢?这与传统的握手有 2 点不同:

  1. 使用 ECDHE 实现秘钥交换,而不是 RSA,所以会在服务端发出“Server Key Exchange” 消息。

  2. 因为使用了 ECDHE,客户端可以不用等到服务器发回 “Finished” 确认握手完毕,就立即发出 HTTP 报文了,节省了一个 RTT 时间。这个叫做 “TLS False Start”,意思就是“抢跑”,和 “TCP Fast Open” 有点像,都是不等连接完全建立就提前发送应用数据来提高传输效率。

下面我们看下传统的 TLS 握手过程:

大体流程没有变,只是 “Pre-Master”(预主密钥) 不再需要用算法生成,而是客户端直接生成随机数,然后用服务器的公钥,通过 “Client Key Exchange” 消息发给服务器。服务器再用私钥解密,这样双方也实现了共享三个随机数,就可以生成主密钥。


说道这里,TLS 的握手基本上就介绍完了。私钥可以说是整个 TLS/SSL 协议中最重要的东西了,结合上面介绍的握手过程,我们再总结下两种握手过程中私钥所起到的作用。

ECDHE 握手时的私钥用途

对于 ECDHE 来说,客户端和服务端双方交换的是椭圆曲线参数,私钥只是用来签名,这是为了保证消息是持有私钥者发送的,而非冒充的。双方交换完参数之后生成预主密钥,再生成主密钥和会话密钥(这里就和 RSA 后面的流程一样了)。

RSA 握手时的私钥用途

对于 RSA 来说,客户端生成预主密钥,然后用公钥加密再发送给服务器,服务器得到预主密钥,然后由预主密钥生成主密钥,再由主密钥生成会话密钥,最后用会话密钥来通信

可以看出 RSA 和 ECDHE 密钥交换算法的私钥用途是不一样的,RSA 密钥交换时私钥用来解密,ECDHE 则是用来签名


SSL/TLS 中预主密钥,主密钥和会话密钥

主密钥是有预主密钥、客户端随机数和服务端随机数通过 PRF 函数生成的;会话密钥是由主密钥、客户端随机数和服务器随机数听过 PRF 函数生成的,会话密钥里面包含对称加密密钥、消息认证和 CBC 模式的初始向量,但对于非 CBC 模式的加密算法来说,就没有用到这个初始向量。

session 缓存和 session ticket 里面保存的主密钥,而不是会话密钥,这是为了保证每次会话都是独立的,这样才能安全。即使一个主密钥泄露了也不影响其他会话。关于该部分将在后面的优化部分再展开介绍。


双向认证

大家平时在登录网上银行时,有时要使用 U 顿给用户颁发客户端证书。其实那就是双向认证,即服务端验证客户端身份。

但是在生活中的绝大多数场景下,我们只是“单向认证” 的握手过程,只认证了服务器的身份,而没有认证客户端的身份。这是因为通常单向认证通过后已经建立了安全通信,再配合账号密码等简单的手段就能够确认客户端的真实身份。

双向认证的流程也没有发生太大的变化,只是在 “Server Hello Done” 之后,“Client Key Exchange” 之前,客户端要发送 “Client Certificate” 消息,服务器收到后也把证书链走一遍,验证客户端的身份。

总结

今天我们主要介绍了 HTTPS/TLS 的握手,整个过程还是比较复杂的。不过为了方便记忆我们可以简单总结为如下几条:

  1. HTTPS 协议在握手之前,需要先进行 TCP 握手,然后执行 TLS 握手,才能建立安全连接;

  2. TLS 握手的目的是安全地交换对称密钥(会话密钥),这个过程需要三个随机数,第三个随机数 “Pre-Master” 必须加密传输,绝对不能让黑客破解;

  3. “Hello” 消息交换随机数,“Key Exchange” 消息交换 “Pre-Master”;

  4. “Change Cipher Spec” 消息之前传输的都是明文,之后都是通过对称密钥加密的密文。

网络安全涉及了方方面面太多的知识,尤其是网络的基础知识对我们来说还是非常重要的,关于这部分大家又有什么要分享的?欢迎你的分享留言或指正。


网络安全系列专题

  • 网络安全 — HTTPS
  • 网络安全的基石(上)— 加密
  • 网络安全的基石(下)— 完整性与身份认证
  • 公钥信任问题 — 数字证书与 CA

扩展阅读

  • HTTPS中CA证书的签发及使用过程
  • HTTPS中SSL/TLS握手时的私钥用途(RSA、ECDHE)

你可能感兴趣的:(信任始于握手 — TLS 1.2 连接过程详解)