安全传输层协议(TLS)全貌解析
一、协议概述
安全传输层协议(Transport Layer Security,简称TLS)是一种密码学协议,旨在为两个通信应用程序之间提供保密性和数据完整性。TLS是SSL(Secure Sockets Layer)协议的继承者,由IETF标准化,目前最新版本为TLS 1.3(RFC 8446,已被RFC 9846更新)。
TLS协议位于传输层(如TCP)与应用层之间,有时被称为”第6.5层协议”。它的设计目标是:认证(服务器端强制认证,客户端可选)、机密性(数据仅对通信端点可见)和完整性(数据不可被篡改而不被察觉)。即便攻击者完全控制网络,这些安全属性也应得到保障。
TLS最大的优势之一是独立于应用协议,HTTP(变为HTTPS)、SMTP、VPN等都可以透明地建立在TLS之上。TLS协议由两个主要组件构成:记录协议和握手协议。
二、TLS记录协议(Record Protocol)
记录协议是TLS的底层传输模块,位于可靠的传输协议(如TCP)之上,负责对上层数据进行封装、加密和完整性保护。记录协议的工作流程为:从高层接收数据 → 分片(每片不超过2^14字节即16KB)→ 可选的压缩(TLS 1.3已移除)→ 计算MAC并加密 → 添加头部 → 通过TCP发送。
2.1 明文记录(TLSPlaintext)
在握手早期,记录以明文形式传输,其结构如下:
| 字段名 | 长度(字节) | 类型 | 描述 |
|---|---|---|---|
type | 1 | ContentType | 内容类型。22=握手,23=应用数据,21=告警,20=变更密码规范(仅兼容性) |
legacy_record_version | 2 | ProtocolVersion | TLS 1.3中固定为0x0303(TLS 1.2版本号),仅用于向下兼容 |
length | 2 | uint16 | 后续fragment字段的长度,最大值16384字节(2^14) |
fragment | 可变(≤16KB) | opaque | 实际负载数据,可以是握手消息、应用数据或告警信息的明文片段 |
2.2 密文记录(TLSCiphertext)
密钥协商完成后,所有记录都被加密传输,其结构如下:
| 字段名 | 长度(字节) | 类型 | 描述 |
|---|---|---|---|
opaque_type | 1 | ContentType | TLS 1.3中恒为23(application_data),真实的内容类型被加密隐藏在负载内部 |
legacy_record_version | 2 | ProtocolVersion | 固定为0x0303 |
length | 2 | uint16 | 后续encrypted_record字段的长度 |
encrypted_record | 可变 | opaque | 使用AEAD算法(如AES-GCM)加密后的数据,包含密文和认证标签,解密后才能还原真实内容类型 |
2.3 内容类型枚举
| 值 | 常量名 | 描述 |
|---|---|---|
| 20 | change_cipher_spec | 变更密码规范(TLS 1.3中已废弃,仅用于兼容性) |
| 21 | alert | 告警消息 |
| 22 | handshake | 握手消息 |
| 23 | application_data | 应用数据 |
三、TLS握手协议(Handshake Protocol)
握手协议是TLS中最复杂的部分,负责对通信双方进行身份认证、协商加密算法和生成共享密钥。所有握手消息都遵循统一的头部格式:
3.1 握手消息通用头部
| 字段名 | 长度(字节) | 类型 | 描述 |
|---|---|---|---|
msg_type | 1 | HandshakeType | 握手消息类型(见下方各消息的具体值) |
length | 3 | uint24 | 后续消息体的长度 |
body | 可变 | opaque | 消息的具体内容,格式因msg_type而异 |
3.2 握手消息类型枚举
| 值 | 常量名 | 描述 |
|---|---|---|
| 1 | client_hello | 客户端发起握手 |
| 2 | server_hello | 服务器响应 |
| 4 | new_session_ticket | 新会话票据(用于恢复) |
| 8 | encrypted_extensions | 加密扩展(TLS 1.3新增) |
| 11 | certificate | 证书消息 |
| 13 | certificate_request | 请求客户端证书 |
| 15 | certificate_verify | 证书验证签名 |
| 20 | finished | 握手完成确认 |
| 24 | key_update | 密钥更新(TLS 1.3新增) |
| 25 | message_hash | 消息哈希(TLS 1.3内部使用) |
3.3 握手流程渲染图
完整的TLS 1.3握手可以清晰地分为三个阶段,如下图所示:

图例说明:
{...}表示消息已加密。从EncryptedExtensions开始到Finished的所有消息都已使用握手密钥加密传输。
四、握手消息字段详解
4.1 ClientHello 消息(msg_type = 1)
ClientHello是握手发起的第一条消息,客户端在此声明其能力和偏好。
| 字段名 | 长度(字节) | 类型 | 描述 |
|---|---|---|---|
legacy_version | 2 | ProtocolVersion | 固定为0x0303(TLS 1.2),实际版本在supported_versions扩展中协商 |
random | 32 | opaque | 客户端生成的32字节随机数,用于密钥派生和防重放攻击 |
legacy_session_id | 1 + 可变(≤32) | opaque | 兼容旧版会话恢复,TLS 1.3中若无可用ID则生成32字节不可预测值 |
cipher_suites | 2 + 可变 | uint16数组 | 客户端支持的加密套件列表,按优先级降序排列。如0x1301=TLS_AES_128_GCM_SHA256 |
legacy_compression_methods | 1 + 可变 | uint8数组 | TLS 1.3中必须只包含0x00(null压缩),不支持压缩功能 |
extensions | 2 + 可变 | Extension数组 | 核心扩展区,包含supported_versions、key_share、pre_shared_key等 |
ClientHello中的关键扩展:
| 扩展名称 | 类型值 | 作用 |
|---|---|---|
supported_versions | 0x002B | 客户端列出所有支持的TLS版本 |
key_share | 0x0033 | 携带(EC)DHE临时公钥,用于前向保密密钥交换 |
pre_shared_key | 0x0029 | PSK身份列表和绑定器,用于会话恢复(必须放在最后) |
psk_key_exchange_modes | 0x002D | 声明PSK支持的交换模式(仅PSK或PSK+DHE) |
signature_algorithms | 0x000D | 声明支持的签名算法(如rsa_pss_rsae_sha256) |
supported_groups | 0x000A | 声明支持的椭圆曲线和有限域群组 |
4.2 ServerHello 消息(msg_type = 2)
服务器对ClientHello的响应,确认选定的参数。
| 字段名 | 长度(字节) | 类型 | 描述 |
|---|---|---|---|
legacy_version | 2 | ProtocolVersion | 固定为0x0303 |
random | 32 | opaque | 服务器生成的32字节随机数,最后8字节可用于版本降级防护(SCSV) |
legacy_session_id_echo | 1 + 可变(≤32) | opaque | 必须原样回显客户端发来的legacy_session_id |
cipher_suite | 2 | uint16 | 服务器从客户端列表中选择的一个加密套件 |
legacy_compression_method | 1 | uint8 | 固定为0(null压缩) |
extensions | 2 + 可变 | Extension数组 | 必须包含key_share扩展,也可包含pre_shared_key等 |
4.3 EncryptedExtensions 消息(msg_type = 8)
服务器发送的已加密扩展,包含了在密钥交换后协商且需要保密的扩展信息。
| 字段名 | 长度(字节) | 类型 | 描述 |
|---|---|---|---|
extensions | 2 + 可变 | Extension数组 | 加密传输的扩展,如server_name(用于SNI)、alpn(应用层协议协商)等 |
此消息在TLS 1.3中为新增,将之前版本中明文传输的扩展移入加密通道,显著增强了隐私保护。
4.4 CertificateRequest 消息(msg_type = 13,可选)
当服务器希望客户端提供证书进行身份认证时发送。
| 字段名 | 长度(字节) | 类型 | 描述 |
|---|---|---|---|
certificate_request_context | 1 + 可变 | opaque | 上下文标识符,服务器用于匹配证书请求和响应 |
extensions | 2 + 可变 | Extension数组 | 指定可接受的证书参数,如signature_algorithms、authorized_keys等 |
4.5 Certificate 消息(msg_type = 11)
用于发送终端(通常是服务器,也可是客户端)的X.509数字证书链。
| 字段名 | 长度(字节) | 类型 | 描述 |
|---|---|---|---|
certificate_request_context | 1 + 可变 | opaque | 若响应CertificateRequest则原样回显,否则为空(0长度) |
certificate_list | 3 + 可变 | CertificateEntry数组 | 一个或多个X.509 DER格式证书组成的证书链 |
extensions | 2 + 可变 | Extension数组 | 应用于整个证书链的扩展,如OCSP Stapling(status_request) |
CertificateEntry内部结构:
| 字段名 | 长度(字节) | 类型 | 描述 |
|---|---|---|---|
cert_data | 3 + 可变 | opaque | X.509 DER编码的单个证书 |
extensions | 2 + 可变 | Extension数组 | 该证书的扩展 |
4.6 CertificateVerify 消息(msg_type = 15)
使用证书对应的私钥对整个握手消息的哈希值进行签名,证明拥有该证书。
| 字段名 | 长度(字节) | 类型 | 描述 |
|---|---|---|---|
algorithm | 2 | SignatureScheme | 签名算法,如0x0804=rsa_pss_rsae_sha256,0x0805=rsa_pss_rsae_sha384 |
signature | 2 + 可变 | opaque | 数字签名值,签名覆盖整个握手过程的哈希(Transcript-Hash) |
常见签名算法值:
| 值 | 算法名称 | 描述 |
|---|---|---|
| 0x0401 | rsa_pkcs1_sha256 | RSA PKCS#1 v1.5 + SHA-256(TLS 1.3中已废弃) |
| 0x0804 | rsa_pss_rsae_sha256 | RSASSA-PSS + SHA-256 |
| 0x0805 | rsa_pss_rsae_sha384 | RSASSA-PSS + SHA-384 |
| 0x0806 | rsa_pss_rsae_sha512 | RSASSA-PSS + SHA-512 |
| 0x0603 | ecdsa_secp256r1_sha256 | ECDSA + SHA-256 |
| 0x0807 | ed25519 | Ed25519签名 |
| 0x0808 | ed448 | Ed448签名 |
4.7 Finished 消息(msg_type = 20)
这是握手过程中第一条使用当前密钥加密发送的消息,用于验证握手过程未被篡改,并提供密钥确认。
| 字段名 | 长度(字节) | 类型 | 描述 |
|---|---|---|---|
verify_data | 可变(32或48) | opaque | 基于所有握手消息计算的验证数据,长度取决于哈希算法(SHA-256为32字节,SHA-384为48字节) |
verify_data的计算方式为:
verify_data = HMAC_Hash(Secret, Transcript-Hash)
其中 Secret 是当前阶段的流量密钥,Transcript-Hash 是累积的所有握手消息的哈希值。
五、告警协议(Alert Protocol)
告警协议用于在通信过程中传递错误或警告信号,作为记录层type=21的fragment内容。
| 字段名 | 长度(字节) | 类型 | 描述 |
|---|---|---|---|
level | 1 | AlertLevel | 1=警告(Warning),2=致命(Fatal)。致命告警导致连接立即终止 |
description | 1 | AlertDescription | 具体告警类型,详见下表 |
常见告警描述值:
| 值 | 常量名 | 描述 |
|---|---|---|
| 10 | unexpected_message | 收到意外消息 |
| 20 | bad_record_mac | MAC校验失败 |
| 21 | decryption_failed | 解密失败(已废弃) |
| 22 | record_overflow | 记录长度溢出 |
| 40 | handshake_failure | 握手失败 |
| 42 | bad_certificate | 证书损坏 |
| 43 | bad_certificate | 证书过期(注意:此描述值实际为43) |
| 44 | decode_error | 解码错误 |
| 46 | certificate_unknown | 证书未知 |
| 47 | illegal_parameter | 非法参数 |
| 86 | internal_error | 内部错误 |
| 116 | missing_extension | 缺少必需扩展 |
六、扩展机制(Extensions)
扩展机制是TLS 1.3灵活性的核心基础,所有扩展使用统一的数据结构:
| 字段名 | 长度(字节) | 类型 | 描述 |
|---|---|---|---|
extension_type | 2 | ExtensionType | IANA注册的扩展类型标识符 |
extension_data | 2 + 可变 | opaque | 扩展的具体数据,格式由extension_type决定 |
6.1 supported_versions 扩展(0x002B)
用于TLS 1.3真正的版本协商。
| 位置 | 字段 | 长度 | 描述 |
|---|---|---|---|
| ClientHello | versions | 2 + 可变 | 客户端支持的所有版本列表,如{0x0303, 0x0304} |
| ServerHello | selected_version | 2 | 服务器选择的版本,如0x0304(TLS 1.3) |
6.2 key_share 扩展(0x0033)
携带(EC)DHE临时公钥,是提供前向保密的核心。
struct {
NamedGroup group; // 群组标识,如 secp256r1(0x0017)
opaque key_exchange<1..2^16-1>; // 公钥数据
} KeyShareEntry;
| 字段 | 描述 |
|---|---|
| ClientHello | 客户端可提供多个KeyShareEntry(每个支持的群组一个) |
| ServerHello | 服务器从客户端提供的列表中选择一个群组,回复对应的公钥 |
| HelloRetryRequest | 若客户端未提供服务器支持的群组,服务器可要求客户端重试 |
常见命名群组值:
| 值 | 群组名称 | 描述 |
|---|---|---|
| 0x0017 | secp256r1 | NIST P-256椭圆曲线 |
| 0x0018 | secp384r1 | NIST P-384椭圆曲线 |
| 0x0019 | secp521r1 | NIST P-521椭圆曲线 |
| 0x001D | x25519 | Curve25519(推荐,高性能) |
| 0x001E | x448 | Curve448 |
| 0x0100 | ffdhe2048 | 有限域DH 2048位 |
| 0x0101 | ffdhe3072 | 有限域DH 3072位 |
6.3 pre_shared_key 扩展(0x0029)
用于PSK身份认证和会话恢复。重要规则:在ClientHello中,此扩展必须放在最后。
struct {
opaque identity<1..2^16-1>; // PSK身份标识
uint32 obfuscated_ticket_age; // 混淆后的票据年龄(用于防重放)
} PskIdentity;
struct {
PskIdentity identities<7..2^16-1>; // PSK身份列表
PskBinderEntry binders<33..2^16-1>; // 绑定器列表,用于验证PSK真实性
} OfferedPsks;
6.4 psk_key_exchange_modes 扩展(0x002D)
声明客户端在使用PSK时支持的密钥交换模式。
| 值 | 模式名称 | 描述 |
|---|---|---|
| 0 | psk_ke | 仅使用PSK,不使用(EC)DHE(不提供前向保密) |
| 1 | psk_dhe_ke | PSK与(EC)DHE结合使用(提供前向保密,推荐) |
规则:若提供了pre_shared_key扩展,则必须同时提供此扩展。服务器不得选择客户端未声明的模式。
6.5 signature_algorithms 扩展(0x000D)
声明支持的数字签名算法,用于证书验证。
| 字段 | 长度 | 描述 |
|---|---|---|
supported_signature_algorithms | 2 + 可变 | SignatureScheme值列表,按优先级降序排列 |
6.6 supported_groups 扩展(0x000A)
声明支持的椭圆曲线和有限域群组,用于ECDHE和DHE密钥交换。
| 字段 | 长度 | 描述 |
|---|---|---|
supported_groups | 2 + 可变 | NamedGroup值列表,按优先级降序排列 |
七、密钥派生与计算(Key Derivation)
TLS 1.3的密钥派生系统基于HKDF(HMAC-based Extract-and-Expand Key Derivation Function),整个派生过程像一条严密的生产线,逐级生产出不同用途的密钥。
7.1 密钥派生流程图

7.1.1 密钥派生阶段说明表
| 阶段 | 输入 | 核心操作 | 输出 | 用途 |
|---|---|---|---|---|
| 阶段一:输入 | PSK(或0) | HKDF-Extract | Early Secret | 早期秘密,作为后续派生的根 |
| 阶段二:早期密钥 | Early Secret | Derive-Secret | client_early_traffic_secret | 保护0-RTT数据 |
| Early Secret | Derive-Secret | derived_secret_1 | 作为盐值输入下一阶段 | |
| 阶段三:握手密钥 | derived_secret_1 + (EC)DHE | HKDF-Extract | Handshake Secret | 握手秘密,作为后续派生的根 |
| Handshake Secret | Derive-Secret | client_handshake_traffic_secret | 保护客户端发送的握手消息 | |
| Handshake Secret | Derive-Secret | server_handshake_traffic_secret | 保护服务器发送的握手消息 | |
| Handshake Secret | Derive-Secret | derived_secret_2 | 作为盐值输入下一阶段 | |
| 阶段四:主密钥 | derived_secret_2 + 0 | HKDF-Extract | Master Secret | 主密钥,作为应用密钥的根 |
| Master Secret | Derive-Secret | client_application_traffic_secret_0 | 保护客户端发送的应用数据 | |
| Master Secret | Derive-Secret | server_application_traffic_secret_0 | 保护服务器发送的应用数据 | |
| Master Secret | Derive-Secret | resumption_master_secret | 生成NewSessionTicket用于会话恢复 |
7.1.2 流量密钥派生公式表
在实际加密通信时,每个阶段的traffic_secret会被进一步展开为具体的加密密钥和IV:
| 密钥类型 | 派生公式 | 说明 |
|---|---|---|
[sender]_write_key | HKDF-Expand-Label(Secret, "key", "", key_length) | 对称加密密钥 |
[sender]_write_iv | HKDF-Expand-Label(Secret, "iv", "", iv_length) | 初始化向量 |
| 密钥更新 | HKDF-Expand-Label(Secret_old, "traffic upd", "", Hash.length) | 新密钥由旧密钥派生 |
其中 Secret 根据阶段选择:
- 握手阶段:
client_handshake_traffic_secret或server_handshake_traffic_secret - 应用阶段:
client_application_traffic_secret_0或server_application_traffic_secret_0
7.1.3 关键函数说明
| 函数 | 全称 | 作用 |
|---|---|---|
| HKDF-Extract | HMAC-based Extract-and-Expand Key Derivation Function – Extract | 从输入材料中提取出固定长度的伪随机密钥,将熵集中化 |
| Derive-Secret | HKDF-Expand-Label 的封装 | 使用特定的标签(Label)从现有秘密派生出新的秘密,确保不同用途的密钥相互独立 |
| HKDF-Expand-Label | HKDF-Expand with Label | 在HKDF-Expand基础上加入”标签”和”上下文”,实现结构化派生,是TLS 1.3中所有密钥派生的原子操作 |
Derive-Secret 的完整定义:
Derive-Secret(Secret, Label, Messages) = HKDF-Expand-Label(Secret, Label, Transcript-Hash(Messages), Hash.length)其中
Transcript-Hash(Messages)是截至当前所有握手消息的累积哈希值,这使得密钥与握手上下文绑定,防止重放和降级攻击。
7.2 流量密钥计算
最终用于加密记录层的密钥和初始化向量(IV)由对应阶段的Secret通过HKDF-Expand-Label函数派生:
| 密钥类型 | 派生公式 | 长度 |
|---|---|---|
| 写密钥(Write Key) | HKDF-Expand-Label(Secret, "key", "", key_length) | 由密码套件决定(如AES-128为16字节) |
| 写IV(Write IV) | HKDF-Expand-Label(Secret, "iv", "", iv_length) | 由密码套件决定(如AES-GCM为12字节) |
密钥更新机制:当需要更新密钥时,新密钥由旧密钥派生:
application_traffic_secret_N+1 = HKDF-Expand-Label(
application_traffic_secret_N,
"traffic upd",
"",
Hash.length
)
7.3 密钥派生阶段说明
| 阶段 | 输入 | 输出 | 用途 |
|---|---|---|---|
| 早期密钥(Early Secret) | PSK(可选)或0 | client_early_traffic_secret | 保护0-RTT数据;若未使用PSK,输入为0 |
| 握手密钥(Handshake Secret) | 早期密钥派生结果 + (EC)DHE共享秘密 | client_handshake_traffic_secretserver_handshake_traffic_secret | 保护EncryptedExtensions、Certificate等握手消息 |
| 主密钥(Master Secret) | 握手密钥派生结果 + 0 | client_application_traffic_secret_0server_application_traffic_secret_0resumption_master_secret | 保护应用数据;生成会话恢复票据 |
八、TLS 1.3 vs TLS 1.2 关键差异
| 特性 | TLS 1.2 | TLS 1.3 |
|---|---|---|
| 握手延迟 | 2-RTT(完整握手) | 1-RTT(完整握手),0-RTT(恢复) |
| 前向保密 | 可选,RSA密钥交换不提供 | 强制,仅支持(EC)DHE和PSK+DHE |
| 密码套件 | 多种AEAD和非AEAD算法(CBC模式) | 仅AEAD(AES-GCM、ChaCha20-Poly1305) |
| 证书加密 | 明文传输(隐私风险) | 加密传输(增强了隐私保护) |
| ChangeCipherSpec | 独立消息 | 已移除(仅用于兼容性) |
| 压缩 | 支持(有安全风险) | 不支持 |
| 签名算法 | 支持多种(包括SHA-1) | 禁用SHA-1和RSA PKCS#1 v1.5 |
| 扩展灵活性 | 有限 | 高度灵活,大量使用扩展 |
| 密钥更新 | 流程复杂 | 简化的KeyUpdate消息 |
| 会话恢复 | Session ID/Session Ticket | 简化的PSK + 票据机制 |
九、安全影响与挑战
TLS 1.3的前向保密特性在提升安全性的同时,也给企业网络安全监控带来了挑战。传统的被动解密技术(依赖保存的私钥解密历史流量)在TLS 1.3中不再有效,因为每个会话的密钥都是临时生成的。企业需要采用替代方案来维持网络可见性,如端点日志收集、中间代理等,但这些方案各有局限。
此外,0-RTT模式虽然大幅减少了连接延迟,但由于数据在完成完整握手前就已发送,存在重放攻击风险,应用程序在使用0-RTT时需要采取适当的防护措施。
十、总结
TLS 1.3通过精妙的分层架构、严格的握手流程、基于HKDF的密钥派生系统和灵活的扩展机制,为互联网通信提供了坚实的安全底座。从记录层的加密封装,到握手阶段的复杂协商,再到不同密钥阶段的隔离设计,TLS 1.3在安全性、性能和隐私保护方面树立了新的标杆。其主要改进——强制前向保密、加密握手信息、精简密码套件——代表了密码协议设计的前沿方向,也为后量子时代的密码升级奠定了坚实基础。