type
status
date
slug
summary
tags
category
icon
password

基本概念

TLS协议的目的就是为网络通信的两端提供一个安全的通道.
具有以下特性:
  • 身份认证
    • 确保交换信息的各方是他们声称的身份
  • 加密
    • 通道上传输的数据仅对两个端点可见.
      不过TLS默认并不隐藏传输数据的长度,但是两端可以向TLS记录中填充数据用来混淆数据长度提升安全性
  • 完整性
    • 验证数据是否并非伪造而来或未遭篡改过

协议组成部分

TLS协议包括两个子协议(TLS 1.3):
  • 握手协议 (Handshake protocol)
    • 协商加密模式和参数,建立共享密钥
      用于抵制篡改.
  • 记录协议(Record protocol)
    • 使用握手协议建立的加密参数保护通信数据.
      记录协议将通信流量划分为一系列的记录(record),每个记录都被独立保护

TLS 1.3 vs TLS 1.2

TLS 1.3与TLS 1.2相比,主要变更有下面这些:
  • 移除了一些过时的对称加密算法,剩下的都是AEAD算法
  • 支持0-RTT (round-trip time,即往返次数)
  • 移除了静态RSA和DH加密套件
  • 所有在ServerHello之后的握手消息现在都是加密的,新引入的EncryptedExtensions消息允许各种以前在ServerHello中以明文形式发送的拓展.
  • 握手状态机进行了重构,删除了不必要的消息,比如ChangeCipherSpec.
  • TLS1.2的协商机制在TLS 1.3中已经废弃了.
简而言之,就是TLS 1.3更安全了,连接速度更快了,但是目前主流的网站应用还是使用的TLS 1.2.(截止2020年底)

TLS 1.2 的问题

TLS 1.2 支持了许多过时的加密功能,比如:
  • RSA密钥传输 : 不提供前向保密性
  • CBC模式密码 : 蛮力和幸运十三攻击
  • RC4流密码 : 在HTTPS中使用不安全
  • 任意DH组: 有漏洞
  • 导出密码 : 有漏洞

TLS 1.3

握手协议

在TCP连接建立之后,会发生TLS握手协议.
握手协议的作用:
  • 协商使用的协议版本
  • 选择加密算法
  • 互相认证(可选)
  • 建立共享密钥
一旦握手完成,客户端和服务端会使用建立的密钥去保护应用层的数据(对称加密).
TLS 支持三种密钥(KEY)交换模式:
  • (EC)DHE
  • PSK-only
  • PSK with (EC)DHE
Client Server Key ^ ClientHello Exch | + key_share* | + signature_algorithms* | + psk_key_exchange_modes* v + pre_shared_key* --------> ServerHello ^ Key + key_share* | Exch + pre_shared_key* v {EncryptedExtensions} ^ Server {CertificateRequest*} v Params {Certificate*} ^ {CertificateVerify*} | Auth {Finished} v <-------- [Application Data*] ^ {Certificate*} Auth | {CertificateVerify*} v {Finished} --------> [Application Data] <-------> [Application Data]

握手协议的3个阶段

  • 密钥交换
    • 建立共享key,选择加密参数,这个阶段之后的数据传输都会被加密.
      ClientHello消息中包含了下面这些信息:
    • 一个随机数
    • TLS协议的版本
    • 加密套件对
    • DH key share
  • 服务器参数
    • 建立其他的握手参数,比如客户端是否认证,应用层协议支持等.
  • 认证
    • 认证服务器,和客户端(可选),提供密钥确认和握手完整性

ClientHello

notion image
 

ServerHello

notion image
 
可以看到在TLS1.3中ServerHello中就会将数据加密传输了.
实际的过程非常复杂,这里暂时不分析了.

TLS 1.2

TLS 1.2 与 TLS1.3 的握手协议过程是不一样的.

握手协议

Client Server ClientHello --------> ServerHello Certificate* ServerKeyExchange* CertificateRequest* <-------- ServerHelloDone Certificate* ClientKeyExchange CertificateVerify* [ChangeCipherSpec] Finished --------> [ChangeCipherSpec] <-------- Finished Application Data <-------> Application Data
看一下更具体的图示吧(ECDHE):
notion image
这个过程抓包就是这样:
notion image
 

RSA密钥交换

notion image
在 RSA 握手中,TLS 握手中创建会话密钥的步骤如下:
  1. 客户端向服务器发送一条明文 “hello” 消息,其中包括他们要使用的协议版本、受支持的密码套件列表和称为“客户端随机数”的随机数据短字符串。
  1. 服务器使用其 SSL 证书、首选密码套件和一个不同的随机数据短字符串(称为“服务器随机数”)响应(以明文格式)。
  1. 客户端创建另一组随机数据,称为“预主机密(pre-master-key)”。客户端从服务器的 SSL 证书中获取公钥,加密预主机密,并将其发送到服务器;只有拥有私钥的人员才能解密预主机密。
  1. 服务器解密预主机密。请注意,这是唯一一次使用私钥!
  1. 现在,客户端和服务器都有客户端随机数、服务器随机数和预主机密。它们彼此独立,将这三个输入组合起来可得到会话密钥。它们都应达到相同的结果,并且会话期间的所有后续通信都用这些新密钥进行加密。
RSA密钥交换使用了三种随机字符串,即客户端的随机数,服务端的随机数,客户端创建的另一组随机数,这三个随机串组合在一起构成了后续加密数据的密钥
还有一种Keyless 的密钥交换机制,即不把私钥放到云服务器厂商那里,而放到自己可以控制的服务器上.
notion image
Cloudflare Keyless SSL Handshake (RSA)

短暂Diffie-Hellman密钥交换

notion image
短暂 Diffie-Hellman (DHE) 握手(“短暂”是因为同一密钥从未使用两次)使用 Diffie-Hellman 算法生成会话密钥,这是一种在不安全通道上交换密钥的方法。通过这种 TLS 握手,私钥身份验证成为独立于会话密钥生成的过程。
除了使用的算法之外,DHE 握手和 RSA 握手之间的主要区别在于如何生成预主机密。在 RSA 握手中,预主机密由客户端生成的随机数据组成。在 DHE 握手中,客户端和服务器使用商定的参数分别计算相同的预主机密。
  1. 就像在 RSA 握手中一样,客户端发送他们要使用的协议版本、受支持的密码套件列表以及客户端随机数
  1. 服务器用其选择的密码套件、服务器随机数和 SSL 证书响应。在这里,DHE 握手开始与 RSA 握手有所不同:服务器还发送其 Diffie-Hellman (DH) 参数,该参数将用于计算预主机密。它还使用服务器的私钥加密客户端随机数、服务器随机数和 DH 参数。这是唯一一次使用私钥,它验证服务器是其声称的身份。
  1. 客户端使用公钥解密服务器的消息并验证 SSL 证书。然后,客户端使用其 DH 参数回复。
  1. 双方使用客户端的 DH 参数和服务器的 DH 参数,彼此分开计算预主机密(pre-master-key)。
  1. 然后,他们将此预主机密与客户端随机数和服务器随机数组合以获取会话密钥。
可以看到这里依然是组合客户端随机数,服务器随机数,pre-master-key组合来生成用于对称加密的密钥.
这里依然有一种keyless的方案
notion image
Cloudflare Keyless SSL (Diffie Hellman)
短暂 Diffie-Hellman 握手尽管比 RSA 握手花费的时间稍长,但有称为前向保密的优点。由于私钥仅用于身份验证,因此攻击者无法使用它来查找任何指定的会话密钥。

RSA vs 短暂DHE

RSA不是前向加密的,安全性不如短暂DHE.

单向认证/双向认证

一般都是单向认证,即服务端认证
但是特殊情况下,客户端也要求认证,比如各种金融银行类APP,一般会内置数字证书进行双向认证.

术语

  • X.509
    • 公钥证书的格式标准.
      常见的格式有:
    • pem : 隐私增强型电子邮件格式,通常是base64格式;
    • cer/crt/der : 通常是二进制格式
  • 前向保密
    • 前向保密确保加密的数据即使私钥公开时仍保持加密,这也称为“完美前向保密”。
      如果每个通信会话使用唯一的会话密钥,并且会话密钥与私钥分开生成,则前向保密是可能的。如果单个会话密钥受损,则攻击者只能解密该会话;所有其他会话都将保持加密状态。(每个会话所使用的密钥是唯一的,不同的)
      在为前向保密设置的协议中,私钥在初始握手过程中用于身份验证,否则不用于加密。短暂 Diffie-Hellman 握手将会话密钥与私钥分开生成,因此具有前向保密。
      相反,RSA 没有前向保密;在私钥受损的情况下,攻击者可以解密过去对话的会话密钥,因为他们可以解密明文形式的预主机密以及客户端随机数和服务器随机数。通过将这三者结合起来,攻击者可以得到任何指定的会话密钥。

参考文档

  1. https://www.rfc-editor.org/rfc/rfc8446.html
  1. https://tools.ietf.org/html/rfc5246
  1. https://www.cloudflare.com/zh-cn/learning/ssl/keyless-ssl/
WebSocket在回顾了多年来的编程学习记录之后…
姜康
姜康
一个软件工程师
公告
type
status
date
slug
summary
tags
category
icon
password
🎉博客网站重新制作了🎉
👏欢迎更新体验👏