TLS CipherSuite 主要由密钥交换方法、身份验证方法、密码定义(包括对称加密算法、安全强度、认证与分组模式)以及可选的 MAC 或 PRF 算法组合而成(如果未采用 AEAD 认证加密方案,则需提供 MAC;若采用 AEAD,则无需单独指定 MAC),示例如下:
密钥交换算法使得通信双方可以在非安全信道中安全地交换用于加密后续通信消息的密钥。常用的密钥交换算法包括:
非对称加密法正向使用(公钥加密,私钥解密)可用于加密信息;逆向使用(私钥加密,公钥解密)可作为数字签名,进行身份验证。该特性主要得益于性质:公钥加密的信息,只有私钥能解密,私钥加密的信息,只有公钥能解密;公钥对外公开,私钥本人持有。常用的非对称加密算法包括:
对称加密算法用于加密传输的数据。由于非对称加密算法加密和解密的效率低(只有对称加密算法的几百分之一),不适合大数据量加解密,所以使用对称加密算法加密应用数据。常用的对称加密算法包括:
对称加密算法的缺陷是,通信双方需要交换密钥,密钥的安全无法得到保证。因此需要借助密钥交换算法交换密钥。TLS 通过密钥交换算法交换会话密钥,通过对称加密算法加密信息
哈希函数用于数据的完整性校验,它以紧凑的方式表示及比较大量数据。其特点如下:
常用的安全哈希算法(Secure Hash Algorithm)包括:
使用哈希散列值可以实现数据完整性检查,能够辨别出“篡改”,但无法辨别出“伪装”。因此对散列值加密后再发送,使用密钥加密后的散列值称为消息认证码(Message Authentication Code)。密文与对应的 MAC 一起发送,由于攻击者不知道密钥,即便修改密文也无法生成合法的 MAC,可以保证散列值不被篡改(前提是密钥未泄露),接收方可以同时辨识出数据的“篡改”和“伪装”。MAC 算法中至少包含一种散列算法,以便获取消息的散列值。常用的 MAC 实现方式包括:
DH 密钥交换(Diffie-Hellman Key Exchange)基于单向函数 - 取模运算(Modular Arithmetic)。单向函数或不可逆函数的特点是:正向计算结果唯一;逆向运算结果不确定。DH 密钥交换的过程如下:
在上述过程中,G、P 被称为域参数,通常由服务器选择域参数,发送给客户端,以约定初始条件。DH 密钥交换的安全性在很大程度上取决于这两个域参数的质量。
在 DH 密钥交换过程中,服务端向客户端提供三个参数(两个域参数和一个计算结果),客户端向服务端提供一个计算结果。服务端的公私密钥是固定的,只有客户端在协商过程中随机生成公私密钥。因此不具备完全前向保密能力 - 即便在密钥泄露的情况下,也不能使用泄露的密钥解密之前捕获的密文。
如果想具备前向保密能力,那么需要每次交换的共享密钥都不相同,即在每个新协商过程中使用临时私钥,具备这种特性的 DH 称为 DHE(Diffie-Hellman Ephemeral)。DHE 是 TLS 1.2/1.3 支持的密钥交换方案。
ECDH(Elliptic Curve Diffie-Hellman Key Exchange,椭圆曲线迪菲-赫尔曼秘钥交换)建立在这样一个前提上:给定椭圆曲线上的一个点 P,一个整数 K,求 Q = K * P 很容易,但是通过 Q、P 求解 K 很难。ECDH 基于 ECC 的以下特性:
(a * G) * b = (b * G) * a
ECDH 密钥交换流程如下:
在 ECDH 密钥交换流程中,服务端使用证书中的公钥,因此必须采用 ECC 证书,ECDH 不具备完全前向保密能力。
在 ECDHE 密钥交换流程中,服务端生成临时“椭圆曲线公钥” Server Params
,使用私钥签名后,将其发送到客户端;客户端也生成临时“椭圆曲线的公钥” Client Params
,发送到服务端。而私钥由服务端和客户端自己保管。
可见,在 ECDHE 中,私钥仅用于签名,ECDHE 具备完全前向保密能力。
RSA 密钥交换流程如下:
可见,在 RSA 密钥交换流程中,如果获得服务端的私钥,那么就可以获得 Pre-Master,进而生成会话密钥,所以 RSA 不具备完全前向保密能力。
安全信道使用的密码参数由 TLS 握手协议生成。当客户端与服务端首次通信时,它们使用 TLS 的该子协议。握手协议允许两端协商协议版本,选择密码参数,可选地认证彼此,建立共享密钥材料。握手完成后,两端使用建立的密钥保护应用层流量。
握手失败或其它协议错误触发连接终止,可在此之前发送警告消息。
TLS 1.3 支持三种基础密钥交换模式:
下面是展示基础的完整 TLS 握手的示意图:
其中:
如上图所示,握手有三个阶段:
在密钥交换阶段,客户端发送 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 消息之前,发送应用数据。注意,尽管服务端在收到客户端的认证消息之前,可以发送应用数据,但此时发送的任何数据都将发送到未认证的对端。