1. 画出 TLS 1.3 的 1-RTT 完整握手消息序列(ClientHello→ServerHello+EncryptedExtensions+Certificate+CertificateVerify+Finished→(Finished)),并指出每条消息的加密时机?
请画出 TLS 1.3 完整握手(1-RTT)的消息序列,并说明每条握手消息在密钥派生流程中的加密时机与保护范围?
- TLS 1.3 握手消息的完整顺序与单次往返(1-RTT)结构
- 每条消息由哪个阶段密钥(early / handshake / application traffic secret)保护
- ClientHello 与 Finished 在不同阶段明文/密文的差异
完整握手流程为:客户端发送 ClientHello(明文,携带 key_share、supported_versions、signature_algorithms 等扩展,其后可选附加的 early 数据);服务器依次发送 ServerHello(明文,随后的消息用 handshake 密钥加密)、EncryptedExtensions(HKDF 派生的 Client/Server Handshake Traffic Secret 加密)、Certificate(同样用 handshake traffic secret 加密)、CertificateVerify(对 transcript 签名,用 server handshake traffic secret 加密)、Finished(握手最后一条保护消息,用 handshake traffic secret 加密);客户端随后发送 Finished(用 client handshake traffic secret 加密)。两条 Finished 之后双方才切换为 application traffic secret 加密应用数据。关键在于:ServerHello 之后的全部服务器握手消息都立即被 handshake 密钥保护,而 ClientHello 必须在服务器看到它之前无法加密,因此只能明文。
加密时机由密钥派生进度决定——消息在派生出对应 traffic secret 之后才被加密。ServerHello 一经发送,双方即可用 HKDF 从 ECDHE 共享密钥与 transcript 派生出 handshake secret,因此其后的消息全部加密。Finished 使用 handshake key 而非 application key,因为它本身是握手认证的一部分,需要先完成对握手 transcript 的校验。1-RTT 意味着只需一次往返(ClientHello 与 ServerHello 之间的往返)即可完成握手。
# 简化的 TLS 1.3 1-RTT 握手消息与加密阶段示意(概念性)
stages = [
("ClientHello", "plaintext/early"),
("ServerHello", "plaintext"),
("EncryptedExtensions", "handshake"),
("Certificate", "handshake"),
("CertificateVerify", "handshake"),
("Finished(server)", "handshake"),
("Finished(client)", "handshake"),
("Application Data", "application"),
]
for msg, stage in stages:
print(f"{msg:20s} -> {stage}")