GM/T 0128-2023 DTLCP 数据报传输层密码协议:国密 UDP 安全通信的协议架构与安全分析

协议详解 · 2026-08-13

概述

传输层密码协议(TLCP,GB/T 38636-2020)是面向 TCP 传输的国密安全协议,广泛用于金融、政务等场景的 HTTPS 国密改造。然而,在 UDP 环境下(如物联网、实时通信、QUIC 等),TLCP 的 TCP 依赖成为瓶颈。

GM/T 0128-2023《数据报传输层密码协议》(DTLCP)正是为解决这一问题而设计的协议。它在 TLCP 基础上添加了 UDP 适配机制:显式序列号、握手消息分段重组、无状态 Cookie、超时重传等,使国密安全通信能够运行在不可靠的数据报传输之上。

DTLCP 的核心设计哲学是「对 TLCP 改动最小化」——复用 TLCP 的密码套件、密钥派生、Finished 校验逻辑,在此基础上仅增加必要的 UDP 适配层。

协议分层架构

DTLCP 协议栈分为三层:

CODE
┌─────────────────────────────────────┐
│        Application Data              │  应用数据
├─────────────────────────────────────┤
│    ChangeCipherSpec (0x14)          │  密码规格变更
├─────────────────────────────────────┤
│    Handshake (0x16)                 │  握手协议
├─────────────────────────────────────┤
│    Alert (0x15)                     │  告警协议
├─────────────────────────────────────┤
│    Record Layer (13 字节头部)        │  记录层
└─────────────────────────────────────┘
           ↓ UDP 报文

与 TLCP 的关键区别:

维度TLCP (TCP)DTLCP (UDP)
序列号隐式 64 位计数器显式 epoch + 48 位 sequence_number
握手消息大小无限制(TCP 流)必须支持分段重组(UDP MTU 限制)
DoS 防护无HelloVerifyRequest + Cookie
超时重传TCP 保证四态状态机自行实现
记录头5 字节13 字节(增加 Epoch + SequenceNumber)

记录层设计

记录头部结构

DTLCP 记录头总计 13 字节:

CODE
0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     Type      |    Version    |       Epoch       |  SeqNum   |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      Sequence Number (续)                     |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                         Length                                |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       Fragment (变长)                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

各字段说明:

字段大小说明
Type1 字节记录类型:握手(22)、密码规格变更(20)、告警(21)、应用数据(23)
Version2 字节协议版本 {0x01, 0x01}
Epoch2 字节密码规格变更计数器,区分密钥阶段
SequenceNumber6 字节(48 位)显式序列号,同 epoch 内单调递增
Length2 字节Fragment 长度
Fragment变长载荷数据

epoch 与 sequence_number 规则

  • 每个 epoch 开始时 sequence_number 初始化为 0
  • 每次发送记录时 sequence_number 单调递增
  • 每次发送 ChangeCipherSpec 时 epoch 单调递增
  • epoch/sequence_number 对必须唯一:在 2 倍 MSL(Maximum Segment Lifetime)时间内 epoch 值不能重用
  • epoch 或 sequence_number 回绕前必须终止连接,重新握手

分片与重组

由于 UDP 报文受 MTU 限制(通常 1500 字节,扣除 IP/UDP 头部后约 1400 字节可用),DTLCP 握手消息必须支持显式分段和重组:

CODE
0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|    msg_type   |             length (3 bytes)                  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          message_seq          |   fragment_offset   |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     fragment_length           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       fragment_data...                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • message_seq:消息序号,用于检测乱序和重复
  • fragment_offset:当前分片在原始消息中的偏移量
  • fragment_length:当前分片的长度

MAC 计算

CBC 模式:

CODE
MAC = HMAC_SM3(write_MAC_secret,
    epoch + sequence_number + type + version + length + fragment)

AEAD 模式(GCM):

CODE
additional_data = epoch + sequence_number + type + version + length

注意:epoch 和 sequence_number 作为附加数据参与 MAC/AEAD 计算,这是 DTLS/DTLCP 与 TLS 的关键区别——TLS 中序列号是隐式的,不进入 MAC 计算。

握手协议

握手状态机

DTLCP 采用四态状态机管理握手过程:

状态职责
PREPARING构造本轮待发送的握手消息(Flight),缓存到发送队列
SENDING将 Flight 的消息序列化并发送。若为最后一轮则转入 FINISHED,否则转入 WAITING
WAITING等待对端响应。三种退出:收到正确消息、超时重传、检测到对端重传
FINISHED握手完成。保持 2×MSL 时间响应对端最后一个 Flight 的重传
状态转换规则:
  • 重传定时器超时:WAITING → SENDING(重发 Flight,backoff 翻倍)
  • 检测到对端重传:WAITING → SENDING(重发 Flight)
  • 收到下一轮消息:WAITING → PREPARING
  • 收到最后一轮消息:WAITING → FINISHED
  • 发送完毕(最后一轮):SENDING → FINISHED
  • FINISHED 收到重传:FINISHED → SENDING

message_seq 维护

每次握手的第一个消息 message_seq = 0,每产生一个新消息 message_seq 加 1。重传时使用相同的 message_seq。接收方维护 next_receive_seq 计数器:

  • message_seq == next_receive_seq → 处理,计数器加 1
  • message_seq < next_receive_seq → 丢弃(重复)
  • message_seq > next_receive_seq → 排队缓存(乱序)

完整握手流程(6 个 Flight)

DTLCP 握手比 TLCP 多一个 Cookie 协商阶段,共 6 个 Flight:

Flight发送方消息Epoch
Flight 1ClientClientHello(cookie=空)0
Flight 2ServerHelloVerifyRequest(含 Cookie)0
Flight 3ClientClientHello(带 Cookie)0
Flight 4ServerServerHello + Certificate + ServerKeyExchange* + CertificateRequest* + ServerHelloDone0
Flight 5ClientCertificate* + ClientKeyExchange + CertificateVerify* + [ChangeCipherSpec] + Finished0→1
Flight 6Server[ChangeCipherSpec] + Finished1
带 * 的消息为可选消息,取决于证书类型和密码套件选择。

Finished 校验数据

CODE
verify_data = PRF(master_secret, finished_label,
                  SM3(handshake_messages))[0..11]
  • finished_label:客户端 "client finished",服务端 "server finished"
  • handshake_messages:从 ClientHello 到本消息之前(不含本消息、CCS、HelloRequest)
  • 不包含:初始 ClientHello(如被替换)和 HelloVerifyRequest
这与 TLCP 的 Finished 计算方式一致,但 DTLS 的 handshake_messages 需要按 message_seq 排序后拼接,而非像 TLS 那样依赖 TCP 流的天然顺序。

CODE
Cookie = HMAC_SM3(Secret, ClientAddr || ClientParams)
  • Secret:Config.CookieSecret,服务端随机密钥,建议 ≥ 16 字节
  • ClientAddr:客户端 UDP 地址(IP:Port,非仅 IP)
  • ClientParams:ClientHello 关键字段序列化(version + random + sessionId + cipherSuites + compressionMethods)

服务端收到带 Cookie 的 ClientHello 后,用相同方式重新计算 expected,与收到的 Cookie 进行常数时间比较(防时序侧信道攻击)。

安全保证

攻击类型防御效果
源 IP 伪造放大攻击攻击者必须能接收 Cookie 响应才能继续握手
半连接资源耗尽Cookie 验证通过前服务端不分配任何连接状态
Cookie 重放服务端定期更换 Secret,旧 Cookie 过期失效

密钥层次结构

DTLCP 的密钥派生与 TLCP 保持一致:

CODE
预主密钥(48 字节)
    ↓ PRF + SM3
主密钥(48 字节)
    ↓ PRF + "key expansion" + server_random + client_random
    ├── client_write_MAC_secret(HMAC-SM3 密钥)
    ├── server_write_MAC_secret
    ├── client_write_key(SM4 加密密钥,16 字节)
    ├── server_write_key
    ├── client_write_IV(SM4-GCM 4 字节 / SM4-CBC 16 字节)
    └── server_write_IV

主密钥计算

CODE
master_secret = PRF(pre_master_secret, "master secret",
                    ClientHello.random + ServerHello.random)[0..47]

SM4 密钥长度

算法key_material_lengthfixed_iv_length
SM4-GCM16 字节4 字节(IV 共 12 字节:4B 固定 + 8B 显式 nonce)
SM4-CBC16 字节16 字节

密码套件

DTLCP 定义了以下密码套件:

密码套件密钥交换加密校验编码值
ECC_SM4_GCM_SM3ECCSM4-GCMSM3{0xe0, 0x13}
ECC_SM4_CBC_SM3ECCSM4-CBCSM3{0xe0, 0x11}
ECDHE_SM4_GCM_SM3ECDHESM4-GCMSM3{0xe0, 0x53}
ECDHE_SM4_CBC_SM3ECDHESM4-CBCSM3{0xe0, 0x51}
ECC 模式优先于 ECDHE:ECC 模式下服务端加密证书公钥固定,客户端直接使用公钥加密预主密钥,无需额外握手交互。

重传定时器

DTLCP 采用指数退避重传策略:

CODE
1s → 2s → 4s → 8s → 16s → 32s → 64s → 64s → ...

调优建议:

网络环境InitialTimeoutMaxTimeout
局域网(低延迟、低丢包)300ms ~ 500ms8s
广域网(互联网)1s ~ 2s60s
高丢包/卫星链路500ms ~ 1s60s

重放保护

DTLCP 采用滑动窗口机制进行重放检测:

  • 最小窗口大小:32
  • 默认窗口大小:64
  • 窗口右边缘:当前会话接收到的最高有效序列号
  • 窗口左边缘:右边缘 - 窗口大小
处理流程:
  • 序列号 < 窗口左边缘 → 丢弃(重放)
  • 序列号在窗口内且已记录 → 丢弃(重复)
  • 序列号在窗口内且为新 → MAC 验证
  • MAC 验证成功 → 更新窗口

PMTU 与路径最大传输单元

报文封装开销

协议封装总开销:18(以太网) + 20(IP) + 8(UDP) + 13(DTLCP) = 59 B

默认 PMTU = 1400 推导:1500 - 59 - 41(余量) = 1400

三种场景

  • 场景 A(记录 ≤ PMTU):一记录一报文
  • 场景 B(记录 > PMTU):拆分为 N 个分片,fragment_offset + fragment_length
  • 场景 C(多记录打包):同一 UDP 报文连续放置多条记录,总长度 ≤ PMTU

安全属性分析

机密性

DTLCP 使用 SM4-GCM 或 SM4-CBC + HMAC-SM3 提供数据机密性。GCM 模式作为 AEAD 算法,同时提供机密性和完整性;CBC 模式通过 Encrypt-then-MAC 方案实现等价安全强度。

完整性

所有记录均经过 SM3-HMAC 或 GCM AEAD 认证,攻击者无法在不被检测的情况下修改数据。

抗重放

通过 epoch + sequence_number 双重机制,配合滑动窗口检错,有效防止重放攻击。窗口大小可配置,默认 64。

DoS 防护

Cookie 机制确保服务端在握手完成前不分配任何连接状态,有效抵御 UDP 放大攻击和半连接耗尽攻击。

与 DTLS 1.2 的对比

维度DTLS 1.2 (RFC 6347)DTLCP (GM/T 0128-2023)
版本号{254, 253}(1's complement){0x01, 0x01}
非对称算法RSA / ECDSASM2(ECC / ECDHE)
分组密码AES (GCM/CBC)SM4 (GCM/CBC)
杂凑算法SHA-256SM3
PRFP_SHA256P_SM3(HMAC-SM3)
签名算法RSA-SHA256, ECDSA-SHA256SM2WithSM3 (0x0704)
双证书不需要需要(签名证书 + 加密证书)
序列号显式 epoch+seq(64 位)显式 epoch+seq(48 位)
重放防护滑动窗口(默认 64)滑动窗口(默认 64,最小 32)
密码套件数数十种4 种(国密专用)
关键差异说明:
  • 双证书要求:DTLCP 要求服务端同时持有 SM2 签名证书和 SM2 加密证书,这是国密标准的强制性要求,与国际标准不同。
  • 序列号长度:DTLS 1.2 使用 64 位序列号,DTLCP 使用 48 位序列号,这是因为国密场景下握手消息更少、连接生命周期更可控。
  • 密码套件精简:DTLCP 仅定义 4 种密码套件,均为 SM2+SM4+SM3 组合,体现了国密标准的统一性要求。

相关实践

参考标准

  • GM/T 0128-2023《数据报传输层密码协议规范》(2023-12-04 发布,2024-06-01 实施)
  • GB/T 38636-2020《信息安全技术 传输层密码协议》(TLCP)
  • RFC 6347《Datagram Transport Layer Security Version 1.2》
  • GB/T 32918《信息安全技术 SM2 椭圆曲线公钥密码算法》
  • GB/T 32905《信息安全技术 SM3 密码杂凑算法》
  • GB/T 32907《信息安全技术 SM4 分组密码算法》