Skip to main content

7. The TLS Handshaking Protocols (TLS握手协议)

TLS握手协议 (TLS Handshake Protocol) 负责以下功能:

  • 协商TLS版本和密码套件
  • 服务器和客户端身份验证
  • 协商加密参数和密钥
  • 检测传输错误

握手协议由三个子协议组成:

7.1. Change Cipher Spec Protocol (更改密码规范协议)

更改密码规范协议 (Change Cipher Spec Protocol) 用于通知对等方, 后续记录将使用新协商的CipherSpec和密钥进行保护. 该协议由单个消息组成, 该消息在当前 (而非待定) CipherSpec下加密和压缩. 该消息由值为1的单个字节组成.

struct {
enum { change_cipher_spec(1), (255) } type;
} ChangeCipherSpec;

ChangeCipherSpec消息在握手期间发送. 接收方收到ChangeCipherSpec消息后必须 (MUST) 更新读取待定状态为读取当前状态. 在收到此消息后立即发送Finished消息, 使用新算法, 密钥和秘密. 在握手完成之前, 实现禁止 (MUST NOT) 发送ChangeCipherSpec消息. 在此消息之后收到的第一条消息必须 (MUST) 是Finished消息.

7.2. Alert Protocol (警报协议)

TLS提供Alert消息以向对等实体传达警报. 与其他消息一样, alert消息也使用当前连接状态进行加密和压缩.

enum { warning(1), fatal(2), (255) } AlertLevel;

enum {
close_notify(0),
unexpected_message(10),
bad_record_mac(20),
decryption_failed_RESERVED(21),
record_overflow(22),
decompression_failure(30),
handshake_failure(40),
no_certificate_RESERVED(41),
bad_certificate(42),
unsupported_certificate(43),
certificate_revoked(44),
certificate_expired(45),
certificate_unknown(46),
illegal_parameter(47),
unknown_ca(48),
access_denied(49),
decode_error(50),
decrypt_error(51),
export_restriction_RESERVED(60),
protocol_version(70),
insufficient_security(71),
internal_error(80),
user_canceled(90),
no_renegotiation(100),
unsupported_extension(110),
(255)
} AlertDescription;

struct {
AlertLevel level;
AlertDescription description;
} Alert;

7.2.1. Closure Alerts (关闭警报)

客户端和服务器必须 (MUST) 在关闭连接的写端之前共享关闭信息. 任何一方都可以通过发送close_notify警报来启动其连接的关闭. 收到关闭警报的任何一方都必须 (MUST) 立即停止通过连接发送新数据. 传输close_notify后, 实现禁止 (MUST NOT) 在该连接上发送任何数据.

7.2.2. Error Alerts (错误警报)

TLS协议中的错误处理非常简单. 当检测到错误时, 检测方发送消息给其对等方. 收到致命警报后, 两方必须 (MUST) 立即关闭连接. 服务器和客户端必须 (MUST) 忘记从失败连接建立的秘密值和密钥.

以下错误警报定义如下:

  • unexpected_message: 接收到不适当的消息. 此警报应该永远不会被正确实现观察到.
  • bad_record_mac: 如果收到带有不正确MAC的记录, 则返回此警报. 此消息始终是致命的 (fatal).
  • record_overflow: 收到的TLSCiphertext记录的长度超过2^14+2048字节, 或解密为超过2^14字节的TLSCompressed记录 (或某些连接状态的其他协商限制). 此消息始终是致命的.
  • handshake_failure: 无法协商一组可接受的安全参数.
  • bad_certificate: 证书已损坏, 包含无法验证的签名等.
  • unsupported_certificate: 不支持的证书类型.
  • certificate_revoked: 证书已被其签名者吊销.
  • certificate_expired: 证书已过期或当前无效.
  • certificate_unknown: 处理证书时出现其他 (未指定) 问题, 导致其无法接受.
  • illegal_parameter: 握手中的字段不正确或与其他字段不一致. 此消息始终是致命的.
  • unknown_ca: 收到了有效的证书链或部分链, 但证书未被接受, 因为无法找到CA证书或无法与已知的信任锚匹配.
  • access_denied: 收到了有效的证书, 但当应用访问控制时, 发送者决定不继续协商.
  • decode_error: 无法解码消息, 因为某个字段超出了指定范围或消息长度不正确. 此消息始终是致命的.
  • decrypt_error: 握手密码学操作失败, 包括无法正确验证签名, 解密密钥交换或验证Finished消息.
  • protocol_version: 对等方尝试协商的协议版本被识别但不受支持.
  • insufficient_security: 当协商失败, 特别是因为服务器需要比客户端支持的更安全的密码时, 返回而不是handshake_failure.
  • internal_error: 与对等方或协议正确性无关的内部错误 (例如内存分配失败) 使其无法继续. 此消息始终是致命的.
  • user_canceled: 此握手因用户取消而被取消.
  • no_renegotiation: 作为对hello请求的响应发送, 或由客户端响应服务器发起的握手尝试. 此消息始终是警告.
  • unsupported_extension: 由不理解某些扩展的服务器发送.

7.3. Handshake Protocol Overview (握手协议概述)

TLS握手协议涉及以下步骤:

  • 交换hello消息以就算法达成一致, 交换随机值, 并检查会话恢复.
  • 交换必要的密码学参数以允许客户端和服务器就预主密钥达成一致.
  • 交换证书和密码学信息以允许客户端和服务器进行身份验证.
  • 从预主密钥和交换的随机值生成主密钥.
  • 向记录层提供安全参数.
  • 允许客户端和服务器验证其对等方已计算相同的安全参数, 并且握手发生时没有被攻击者篡改.

注意: 本文档仅提供TLS 1.2握手协议的概述. 完整的技术细节请参考RFC 5246原文第7.4节及后续章节.

7.4. Handshake Protocol (握手协议)

TLS握手协议是TLS记录层的客户端之一. 此协议用于协商连接的安全属性. 握手消息在TLS记录层提供, 其中它们被封装在一个或多个TLSPlaintext结构中, 这些结构根据当前活动连接状态进行处理和传输.

enum {
hello_request(0), client_hello(1), server_hello(2),
certificate(11), server_key_exchange (12),
certificate_request(13), server_hello_done(14),
certificate_verify(15), client_key_exchange(16),
finished(20), (255)
} HandshakeType;

struct {
HandshakeType msg_type;
uint24 length;
select (HandshakeType) {
case hello_request: HelloRequest;
case client_hello: ClientHello;
case server_hello: ServerHello;
case certificate: Certificate;
case server_key_exchange: ServerKeyExchange;
case certificate_request: CertificateRequest;
case server_hello_done: ServerHelloDone;
case certificate_verify: CertificateVerify;
case client_key_exchange: ClientKeyExchange;
case finished: Finished;
} body;
} Handshake;

握手协议消息以显式长度呈现, 不能跨越握手记录边界分段. 也就是说, 每个握手消息必须完全适合单个握手记录或跨越多个握手记录, 每个记录包含整数个握手消息. 接收方必须 (MUST) 检查没有其他数据在握手消息后跟随相同的握手记录, 除非该数据本身是有效的握手消息.

完整的握手消息类型和详细格式, 请参阅RFC 5246第7.4节的各个子节.