基本概念

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 从应用层接收数据并且做以下处理:

  1. 分片,逆向就是重组
  2. 为每个数据块生成唯一编号,防止被重复或重排序
  3. 压缩,根据握手协议协商出的算法做压缩
  4. 加密,根据握手协议协商出的 key 做加密解密
  5. 算 HMAC ,对数据做 HMAC ,并且验证受到数据包 HMAC 正确性
  6. 将数据给传输层

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 身份

现在大多数情况进行身份认证的方式都是通过数字证书: 数字证书的作用

下面的流程就是基于数字证书的握手。

单向认证

  1. 协商阶段
    1. 客户端发送 ClientHello 消息,指定它支持的最高的版本,随机数,建议的加密算法列表和建议的压缩方法。 如果客户端执行恢复握手,消息可能包括会话 id 。 如果客户端可以使用应用层协议协商,消息可能包括支持的应用层协议,如 HTTP/2
    2. 服务器用一条 Server Hello 消息响应,消息包含从客户端提供的选项中选择的协议版本,随机数,加密算法和压缩方法。 如果服务端允许恢复握手,消息中包括会话 id 。 所选的协议版本应该是客户端和服务器都支持的最高版本。
    3. 服务器发送它的证书(Certificate)消息,具体内容依赖加密算法。
    4. 服务器发送它的密钥交换消息(Server Key Exchange)消息,具体内容依赖加密算法。
    5. 服务器发送 Server Hello Done 消息,标识服务器协商结束。
    6. 客户端发送密钥交换信息 ClientKeyExchange ,具体内容依赖加密算法,可能是预主密钥(PreMasterSecret),公钥或空。
    7. 客户端和服务器根据随机数和预主密钥计算出一个公共密钥,叫主密钥(MasterSecret),后面的消息用主密钥加解密。
  2. 客户端发送 ChangeCipherSpec record ,告诉服务器现在所有的消息都是经过验证和加密的。
    • 客户端会发送经过身份验证和加密的 Finished 消息,包括之前握手消息的 hash 和 MAC
    • 服务器尝试解密 Finished 消息,验证 hash 和 MAC ,如果失败则握手失败,终止连接
  3. 服务器发送 ChangeCipherSpec record ,告诉客户端现在所有的消息都是经过验证和加密的。
    • 服务端会发送经过身份验证和加密的 Finished 消息,包括之前握手消息的 hash 和 MAC
    • 客户端尝试解密 Finished 消息,验证 hash 和 MAC ,如果失败则握手失败,终止连接
  4. 握手阶段完成,客户端和服务器的消息会进程身份认证和选择性加密

双向认证

双向认证即服务器也需要认证客户端的有效性。 协议与单向认证不同在协商阶段,服务器发送 Server Hello Done 消息之后:

  1. 客户端发送它的证书

  2. 客户端发送密钥交换信息 ClientKeyExchange ,具体内容依赖加密算法,可能是预主密钥(PreMasterSecret),公钥或空。

  3. 客户端发送 CertificateVerify 消息。消息内容是用客户端证书私钥在前面握手消息上的签名,服务端可以用客户端公钥 验证签名。这让服务器能够确认客户端可以访问证书的私钥,从而拥有证书。

  4. 客户端和服务器根据随机数和预主密钥计算出一个公共密钥,叫主密钥(MasterSecret),后面的消息用主密钥加解密。


  1. https://en.wikipedia.org/wiki/Transport%5FLayer%5FSecurity ↩︎