SSL/TLS 通信的基本流程
基本概念
SSL1(Secure Sockets Layer ,安全套接字层)和 TLS(Transport Layer Security, 传输层安全) 是一种加密协议,目的是为计算机网络提供通信安全。TLS 是已经废弃的 SSL 的继承者,发展过程:
SSL1.0 -> SSL2.0 -> SSL3.0 -> TLS1.0 -> TLS1.1 -> TLS1.2 -> TLS1.3
TLS 协议在传输层之上,应用层数据经过 TLS 层处理后再向下到传输层。 TLS 本身包括 TLS record 协议和 TLS 握手协议。
TLS record 包协议
record 包协议主要是对应用数据做对称加密传输,record 从应用层接收数据并且做以下处理:
- 分片,逆向就是重组
- 为每个数据块生成唯一编号,防止被重复或重排序
- 压缩,根据握手协议协商出的算法做压缩
- 加密,根据握手协议协商出的 key 做加密解密
- 算 HMAC ,对数据做 HMAC ,并且验证受到数据包 HMAC 正确性
- 将数据给传输层
record 数据包格式如下图所示:
ContentType 包括数据包的类型
Hex | Type | 说明 |
---|---|---|
0x14 | ChangeCipherSpec | 更新密码规范 |
0x15 | Alert | 警告消息 |
0x16 | Handshake | 握手包 |
0x17 | Application | 应用数据包 |
0x18 | Heartbeat | 心跳包 |
TLS 握手协议
为了保证服务端和客户端身份的正确性,即防止假冒客户端或假冒服务端,同时服务端与客户端也要协商 record 协议中用到的各种加密算法, TLS 握手协议就是处理这个事情。
客户端需要验证服务端身份,而服务端不需要验证客户端身份的情况叫:单向认证,如常见的 HTTPS 。
客户端和服务端需要互相认证的情况叫:双向认证。如启用 tls 的 mqtt broker ,client 需要验证 broker 身份, broker 要验证 client 身份
现在大多数情况进行身份认证的方式都是通过数字证书。
下面的流程就是基于数字证书的握手。
单向认证
- 协商阶段
- 客户端发送
ClientHello
消息,指定它支持的最高的版本,随机数,建议的加密算法列表和建议的压缩方法。如果客户端执行恢复握手,消息可能包括会话 id 。如果客户端可以使用应用层协议协商,消息可能包括支持的应用层协议,如 HTTP/2 - 服务器用一条
Server Hello
消息响应,消息包含从客户端提供的选项中选择的协议版本,随机数,加密算法和压缩方法。如果服务端允许恢复握手,消息中包括会话 id 。所选的协议版本应该是客户端和服务器都支持的最高版本。 - 服务器发送它的证书(=Certificate=)消息,具体内容依赖加密算法。
- 服务器发送它的密钥交换消息(=Server Key Exchange=)消息,具体内容依赖加密算法。
- 服务器发送
Server Hello Done
消息,标识服务器协商结束。 - 客户端发送密钥交换信息
ClientKeyExchange
,具体内容依赖加密算法,可能是预主密钥(PreMasterSecret),公钥或空。 - 客户端和服务器根据随机数和预主密钥计算出一个公共密钥,叫主密钥(MasterSecret),后面的消息用主密钥加解密。
- 客户端发送
- 客户端发送
ChangeCipherSpec
record ,告诉服务器现在所有的消息都是经过验证和加密的。- 客户端会发送经过身份验证和加密的
Finished
消息,包括之前握手消息的 hash 和 MAC - 服务器尝试解密
Finished
消息,验证 hash 和 MAC ,如果失败则握手失败,终止连接
- 客户端会发送经过身份验证和加密的
- 服务器发送
ChangeCipherSpec
record ,告诉客户端现在所有的消息都是经过验证和加密的。- 服务端会发送经过身份验证和加密的
Finished
消息,包括之前握手消息的 hash 和 MAC - 客户端尝试解密
Finished
消息,验证 hash 和 MAC ,如果失败则握手失败,终止连接
- 服务端会发送经过身份验证和加密的
- 握手阶段完成,客户端和服务器的消息会进程身份认证和选择性加密
双向认证
双向认证即服务器也需要认证客户端的有效性。协议与单向认证不同在协商阶段,服务器发送 Server Hello Done
消息之后:
客户端发送它的证书
客户端发送密钥交换信息
ClientKeyExchange
,具体内容依赖加密算法,可能是预主密钥(PreMasterSecret),公钥或空。客户端发送
CertificateVerify
消息。消息内容是用客户端证书私钥在前面握手消息上的签名,服务端可以用客户端公钥验证签名。这让服务器能够确认客户端可以访问证书的私钥,从而拥有证书。客户端和服务器根据随机数和预主密钥计算出一个公共密钥,叫主密钥(MasterSecret),后面的消息用主密钥加解密。