1. 概览

TLS CipherSuite 主要由密钥交换方法、身份验证方法、密码定义(包括对称加密算法、安全强度、认证与分组模式)以及可选的 MAC 或 PRF 算法组合而成(如果未采用 AEAD 认证加密方案,则需提供 MAC;若采用 AEAD,则无需单独指定 MAC),示例如下:

tls-cipher-suite-demo.webp


2. 密钥交换算法

2.1. DH 密钥交换

DH 密钥交换(Diffie-Hellman Key Exchange)基于单向函数 - 取模运算(Modular Arithmetic)。单向函数或不可逆函数的特点是:正向计算结果唯一;逆向运算结果不确定。DH 密钥交换的过程如下:

  1. Alice 和 Bob 约定使用 GX MOD P 函数(其中 G、P 是质数,比如 G = 7、P = 101)
  2. Alice 选择数 A(比如 A = 3);Bob 选择数 B(比如 B = 6)
  3. 他们分别将自己选择的数带入函数 GX MOD P,假设 Alice 得到 α,Bob 得到 β
  4. 两人将计算结果告诉对方。假设整个通信被 Eve 偷听,由于 Eve 偷听到的只是模运算的结果,由于该过程不可逆,所以其无法推导出执行模运算之前的值
  5. Alice 和 Bob 得到对方的结果后,Alice 执行运算 βA MOD P(即 GA·B MOD P),Bob 执行运算 αB MOD P(即 GA·B MOD P)
  6. 他们将得到完全相同的结果,即会话密钥

在上述过程中,G、P 被称为域参数,通常由服务器选择域参数,发送给客户端,以约定初始条件。DH 密钥交换的安全性在很大程度上取决于这两个域参数的质量。

2.2. 完全前向保密(Perfect Forward Secrecy)

在 DH 密钥交换过程中,服务端向客户端提供三个参数(两个域参数和一个计算结果),客户端向服务端提供一个计算结果。服务端的公私密钥是固定的,只有客户端在协商过程中随机生成公私密钥。因此不具备完全前向保密能力 - 即便在密钥泄露的情况下,也不能使用泄露的密钥解密之前捕获的密文

如果想具备前向保密能力,那么需要每次交换的共享密钥都不相同,即在每个新协商过程中使用临时私钥,具备这种特性的 DH 称为 DHE(Diffie-Hellman Ephemeral)。DHE 是 TLS 1.2/1.3 支持的密钥交换方案。

2.3. ECDH 密钥交换

ECDH(Elliptic Curve Diffie-Hellman Key Exchange,椭圆曲线迪菲-赫尔曼秘钥交换)建立在这样一个前提上:给定椭圆曲线上的一个点 P,一个整数 K,求 Q = K * P 很容易,但是通过 Q、P 求解 K 很难。ECDH 基于 ECC 的以下特性:

ECDH 密钥交换流程如下:

AliceBobAlice 计算 SharedKey = BobPubKey * AlicePrivKeyBob 计算 SharedKey = AlicePubKey * BobPrivKey至此,Alice 和 Bob 拥有相同的 SharedKey生成 ECC 密钥对。{AlicePrivKey, AlicePubKey = AlicePrivKey * G}将 AlicePubKey 和 G 发送给 Bob生成 ECC 密钥对。{BobPrivKey, BobPubKey = BobPrivKey * G}将 BobPubKey 发送给 AliceAliceBob

在 ECDH 密钥交换流程中,服务端使用证书中的公钥,因此必须采用 ECC 证书,ECDH 不具备完全前向保密能力。

2.4. ECDHE 密钥交换

在 ECDHE 密钥交换流程中,服务端生成临时“椭圆曲线公钥” Server Params,使用私钥签名后,将其发送到客户端;客户端也生成临时“椭圆曲线的公钥” Client Params,发送到服务端。而私钥由服务端和客户端自己保管。

可见,在 ECDHE 中,私钥仅用于签名,ECDHE 具备完全前向保密能力。

2.5. RSA 密钥交换

RSA 密钥交换流程如下:

客户端服务端至此,服务端拥有 Client Random 和 Server Random至此,客户端拥有 Client Random、Server Random 和服务端证书至此,客户端和服务端都拥有 Client Random、Server Random 和 Pre Master客户端和服务端使用相同的算法利用它们生成会话密钥发送 Client Hello 消息,其中包含 Client Random发送 Server Hello 消息,其中包含 Server Random发送 Certificate 消息发送 Server Hello Done 消息生成预主密钥 Pre Master发送 Client Key Exchange 消息,其中包含用服务端公钥加密的 Pre Master使用私钥解密 RSA 算法加密的 Pre Master,得到 Pre Master客户端服务端

可见,在 RSA 密钥交换流程中,如果获得服务端的私钥,那么就可以获得 Pre-Master,进而生成会话密钥,所以 RSA 不具备完全前向保密能力。


3. 基于 ECDHE 的 TLS 1.2 握手流程

客户端服务端Client Hello:TLS VersionClient RandomSession IDCipher SuitesServer Hello:TLS VersionServer RandomCipher SuiteServer Key ExchangeNamed CurvePubkeySignature AlgorithmSignatureClient Key Exchange:Pubkey告诉对端,从此刻起,使用协商出的密钥加密和解密消息加密握手消息的作用包括:1. 验证对称密钥是否正确;2. 使服务端验证握手数据是否被篡改发送 Client Hello 消息发送 Server Hello 消息发送 Certificate 消息发送 Server Key Exchange 消息发送 Server Hello Done 消息发送 Client Key Exchange 消息发送 Change Cipher Spec 消息发送 Encrypted Handshake Message 消息发送 Change Cipher Spec 消息发送 Encrypted Handshake Message 消息客户端服务端

4. TLS 1.3 握手流程

TLS RFC:https://www.rfc-editor.org/rfc/rfc8446

安全信道使用的密码参数由 TLS 握手协议生成。当客户端与服务端首次通信时,它们使用 TLS 的该子协议。握手协议允许两端协商协议版本,选择密码参数,可选地认证彼此,建立共享密钥材料。握手完成后,两端使用建立的密钥保护应用层流量。

握手失败或其它协议错误触发连接终止,可在此之前发送警告消息。

TLS 1.3 支持三种基础密钥交换模式:

下面是展示基础的完整 TLS 握手的示意图:

tlsv13handshake.png

其中:

如上图所示,握手有三个阶段:

在密钥交换阶段,客户端发送 ClientHello 消息,其中包含随机数(ClientHello.random);提议的协议版本;对称加密算法/HKDF 哈希对的列表;一组 DH 密钥共享(在 “key_share” 扩展中)和/或一组预共享密钥标签(在 “pre_shared_key” 扩展中);以及其它扩展。

也可能出现其它字段和/或消息,以实现 middlebox 兼容性。

服务端处理 ClientHello,确定连接的响应密码参数。然后使用其自己的 ServerHello(表示协商的连接参数)响应。ClientHello 和 ServerHello 的组合确定共享密钥。如果使用 (EC)DHE 密钥协商,那么 ServerHello 包含具有服务端的临时 Diffie-Hellman 共享密钥的 “key_share” 扩展;服务端的共享密钥必须与客户端的共享密钥中的某一个密钥处于同一组。如果使用 PSK 密钥协商,那么 ServerHello 包含表明选择客户端提供的哪个 PSK 的 “pre_shared_key” 扩展。注意,实现可以同时使用(EC)DHE 和 PSK,在这种情况下,将提供两个扩展。

然后,服务端发送两个消息,以建立服务端参数:

EncryptedExtensions:对特定于单独的证书之外的、不需要确定密码参数的 ClientHello 扩展做出响应。

CertificateRequest:如果需要使用基于证书的客户端身份验证,那么需要指定所需的证书参数。如果不需要客户端认证,那么此消息将被省略。

最后,客户端和服务端交换认证消息。TLS 在每次需要基于证书的身份验证时,使用相同的消息集。(基于 PSK 的身份验证作为密钥交换的副作用发生。)具体地讲:

Certificate:端点的证书和任意证书扩展。如果服务端不使用证书进行身份验证,那么该消息将被服务端忽略,如果服务端未发送 CertificateRequest,那么客户端将省略该消息(这表明客户端不应使用证书进行身份验证)。注意,如果使用原始公钥或缓存的信息扩展,那么该消息将不包含证书,而包含相应于服务器长期密钥的其它值。

CertificateVerify:使用与 Certificate 消息中的公钥对应的私钥对整个握手过程进行的签名。如果端点不通过证书进行身份验证,那么省略该消息。

Finished:对整个握手过程进行的消息认证码(MAC)。该消息提供密钥确认,将端点的身份绑定到交换的密钥,在 PSK 模式中也认证握手。

收到服务端的消息后,客户端将回复自己的认证消息,即 Certificate 和 CertificateVerify(如果需要的话)以及 Finished。

此时,握手过程完成,客户端和服务端派生记录层需要的密钥材料,以交换经过认证加密保护的应用数据。不能在发送 Finished 消息之前,发送应用数据。注意,尽管服务端在收到客户端的认证消息之前,可以发送应用数据,但此时发送的任何数据都将发送到未认证的对端。