聚焦 3GPP TS 33.501 Annex A.9 / A.10 / A.11 与 Section 6.9.2 中接入层(AS)密钥在切换场景下的推演与前向安全机制,区别于已覆盖的"5G AKA认证与密钥推演"(NAS/认证层 KSEAF→KAMF)。本文专门拆解空口 RRC/UP 密钥 KgNB 的产生、NH(Next Hop)/ NCC 密钥链,以及水平/垂直推演如何在不同切换中保证密钥新鲜性与前向安全。
很多工程师把"5G安全"等同于"5G AKA认证"。这其实只覆盖了认证层:USIM与UDM/ARPF持有的永久密钥 K,经 AKA 产生 CK/IK,在 AUSF 衍生 K~AUSF~,再到 SEAF 衍生 K~SEAF~,最终在 AMF 衍生 K~AMF~。至此,UE 与 AMF 共享了 NAS 层的锚密钥。
但用户面和控制面真正在空口(UE ↔ gNB)上传输时,加密/完整性保护用的是另一组密钥:K~RRCint~、K~RRCenc~、K~UPint~、K~UPenc~。这组密钥的根是 KgNB,由 K~AMF~ 推演而来。它们的设计难点不在"产生",而在移动性:
这套矛盾正是 NH(Next Hop)参数 + NCC(Next Hop Chaining Counter)+ 水平/垂直推演 机制要解决的,规范集中在 TS 33.501 Section 6.9.2(Key handling in handover) 和 Annex A.9/A.10/A.11。
下图标出完整层级,红色框即本文聚焦的 AS 子树(KgNB 及其派生):
graph TD
K[永久密钥 K<br/>USIM / UDM-ARPF]
CKIK[CK, IK<br/>AKA衍生于USIM]
KAUSF[K_AUSF<br/>AUSF - Annex A.2]
KSEAF[K_SEAF<br/>SEAF - Annex A.6]
KAMF[K_AMF<br/>AMF/UE - Annex A.7]
KNAS[NAS密钥<br/>K_NASint / K_NASenc<br/>Annex A.8]
KgNB["KgNB<br/>UE与gNB共享 - Annex A.9<br/>输入: K_AMF + 上行NAS COUNT"]
NH["NH Next Hop<br/>Annex A.10<br/>前向安全中间密钥"]
KRRCint[K_RRCint 完整性]
KRRCenc[K_RRCenc 加密]
KUPint[K_UPint UP完整性]
KUPenc[K_UPenc UP加密]
K --> CKIK
CKIK --> KAUSF
KAUSF --> KSEAF
KSEAF --> KAMF
KAMF --> KNAS
KAMF -->|"垂直(初次)"| KgNB
KgNB --> NH
KgNB --> KRRCint
KgNB --> KRRCenc
KgNB --> KUPint
KgNB --> KUPenc
classDef focus fill:#ffe0e0,stroke:#c0392b,stroke-width:2px;
classDef nas fill:#e8f4fd,stroke:#2980b9;
class KgNB,NH,KRRCint,KRRCenc,KUPint,KUPenc focus;
class KNAS nas;
归属实体速记(关键,决定谁能推演什么):
| 密钥 | 持有实体 | 用途 |
|---|---|---|
| K / CK / IK | USIM + UDM/ARPF | 认证根,永不下发 |
| K~AUSF~ | AUSF + UE(ME) | 认证结果锚 |
| K~SEAF~ | SEAF + UE | 服务网络绑定 |
| K~AMF~ | AMF + UE(ME) | NAS锚,推演AS密钥的总根 |
| KgNB | AMF + UE + gNB | gNB空口根密钥 |
| NH | AMF + UE(gNB只持有一个) | 切换前向安全中间量 |
| K~RRC~/K~UP~ | gNB + UE | 真正的空口加密/完整性密钥 |
注意一个关键设计:gNB 永远拿不到 K~AMF~。AMF 只把 KgNB 和"一个 NH"下发给 gNB。这正是前向安全的根基——下文详述。
3GPP 所有密钥推演统一使用一个 KDF,定义在 TS 33.220 Annex B.2,在 33.501 Annex A.1 中引用:
KDF(K, S) = HMAC-SHA-256(K, S) 输出截断到所需比特长度
S = FC || P0 || L0 || P1 || L1 || ... || Pn || Ln
K:输入密钥(父密钥)FC:1字节的函数编码(区分"推演什么密钥")Pi:第 i 个输入参数;Li:Pi 的长度(2字节大端)不同密钥只是 FC 和参数不同。下表列出 AS 密钥链相关的推演函数(Annex A 编号即规范章节):
| 推演函数 | 父密钥 K | FC | 输入参数 P0 / P1 | 产物 | 规范定位 |
|---|---|---|---|---|---|
| A.7 K~AMF~ | K~SEAF~ | — | SUPI、ABBA | K~AMF~ | 注册时建立 |
| A.8 算法密钥 | KgNB 或 K~AMF~ | 0x69 | 算法类型区分符、算法标识 | K~RRCint/enc~、K~UPint/enc~、K~NASint/enc~ | SMC 时按算法派生 |
| A.9 KgNB | K~AMF~ | 0x15 | 上行 NAS COUNT(4字节) | KgNB | 初始/状态转移时 |
| A.10 NH | K~AMF~ | 0x11 | SYNC(首个=KgNB,后续=上一个NH) | NH | 切换前向安全 |
| A.11 KgNB* | KgNB(水平)或NH(垂直) | — | 目标 PCI、下行 ARFCN | 新 gNB 的 KgNB | 切换时 |
设计要点 1:A.9 中 KgNB 绑定上行 NAS COUNT——这是注册后第一个 K~AMF~ 能"新鲜化"的、UE 和 AMF 双方已知且单调的量,保证每次激活安全上下文得到的 KgNB 不同,且无须额外协商。
设计要点 2:A.11 中 KgNB* 绑定目标小区的 PCI 与下行频点 ARFCN-DL——把密钥与"具体某个物理小区"绑死,防止跨小区密钥复用。
AKA 完成后,UE(ME) 和 AMF 各自持有相同的 K~AMF~。随后发生以下推演(独立、无需交互,两边算出相同结果):
sequenceDiagram
participant USIM
participant ME as UE(ME)
participant AMF
participant gNB as gNB(服务)
Note over ME,AMF: AKA完成, 双方持有 K_AMF
ME->>ME: KgNB = KDF(K_AMF, FC=0x15, 上行NAS_COUNT)<br/>(Annex A.9)
AMF->>AMF: KgNB = KDF(K_AMF, FC=0x15, 上行NAS_COUNT)
Note over ME,AMF: 初始 KgNB 对应 NCC=0
ME->>ME: NH_1 = KDF(K_AMF, FC=0x11, SYNC=KgNB)<br/>(Annex A.10, 首个NH)
AMF->>AMF: NH_1 = KDF(K_AMF, FC=0x11, SYNC=KgNB)
Note over ME,AMF: 第一个 NH 对应 NCC=1
AMF->>gNB: NGAP INITIAL CONTEXT SETUP REQUEST<br/>携带: KgNB + {NH_1, NCC=1} + 算法列表
Note over gNB: gNB 持有: 当前KgNB(NCC=0) + 一个NH储备(NCC=1)
Note over gNB: gNB 无法获得 K_AMF, 故无法自行滚动NH链
gNB-->>ME: AS Security Mode Command (算法协商)
Note over gNB,ME: 双方按A.8派生 K_RRCint/enc, K_UPint/enc
这里有两个常被忽视的细节:
切换时,源 gNB 要为目标 gNB 准备新密钥 KgNB*。规范(33.501 6.9.2.1.1,Figure 6.9.2.1.1-1)定义了二维密钥链模型:
graph TD
subgraph 垂直方向[垂直推演 - 用NH, 提供前向安全]
KAMF2[K_AMF] --> NH0[NH_1 NCC=1]
NH0 --> NH1[NH_2 NCC=2]
NH1 --> NH2[NH_3 NCC=3]
end
subgraph 水平方向[水平推演 - 用当前KgNB, 仅新鲜性]
K0[KgNB NCC=0] -->|KDF PCI+freq| K0a[KgNB* NCC=0]
K0a -->|KDF PCI+freq| K0b[KgNB* NCC=0]
end
NH0 -.->|垂直派生目标密钥| K0
NH1 -.-> K0a
两条推演路径的规则:
为什么水平没有前向安全、垂直有?
| 维度 | 水平推演 | 垂直推演 |
|---|---|---|
| 父密钥 | 当前 KgNB(gNB 自己有) | NH(gNB 只有当前一个) |
| NCC 变化 | 不变 | +1 |
| 新鲜性 | ✅(绑定目标PCI/freq) | ✅ |
| 前向安全 | ❌ | ✅ |
| 源gNB能否推算"再下一跳"密钥 | ✅(它有KgNB就能算) | ❌(滚动NH需要K_AMF) |
| 适用场景 | 同频小区快速连续切换 | 关键切换、需前向安全 |
| 规范来源 | 33.501 6.9.2.1.1 / A.11 | 33.501 6.9.2.1.1 / A.11 |
直观理解:水平链里,密钥像 K → K1 → K2,知道任意一个就能往后算,所以一旦 gNB 被攻破,后续水平切换密钥全部暴露。垂直链里,密钥像 K_AMF → NH1 → NH2,而 gNB 没有 K_AMF,被攻破后它手上的 NH~n~ 只够推算当前这一跳,算不出 NH~n+1~,于是后续垂直切换密钥对它是黑箱。
sequenceDiagram
participant UE
participant Src as 源gNB
participant Tgt as 目标gNB
participant AMF
Note over Src: 决策: 用水平(当前KgNB) 还是 垂直(储备NH)
Note over Src: 示例: 选择垂直推演获得前向安全
Src->>Src: KgNB* = KDF(NH_1, PCI_tgt, ARFCN-DL_tgt)<br/>NCC_new = 1
Src->>Tgt: XnAP HANDOVER REQUEST<br/>携带: KgNB* + NCC=1 + 安全算法
Note over Tgt: 存为当前KgNB(NCC=1), 但没有新的NH储备
Tgt-->>Src: XnAP HANDOVER REQUEST ACKNOWLEDGE
Src->>UE: RRCReconfiguration (含 reconfigurationWithSync)<br/>携带: nextHopChainingCount = NCC = 1
Note over UE: 收到NCC=1, 与本地NCC比较
Note over UE: 本地NCC=0 < 收到的1 => 垂直推演
UE->>UE: 先把本地NH链滚到NCC=1<br/>(UE有K_AMF, 可算NH_1)<br/>再 KgNB* = KDF(NH_1, PCI_tgt, ARFCN)
UE-->>Tgt: RRCReconfigurationComplete (用新密钥)
Tgt->>AMF: NGAP PATH SWITCH REQUEST
AMF-->>Tgt: PATH SWITCH REQUEST RESPONSE
Note over AMF,Tgt: AMF下发新的 NH + NCC=2<br/>(UE CONTEXT MODIFICATION)<br/>补充目标gNB的前向安全储备
UE 侧判别水平/垂直的关键:UE 在 RRCReconfiguration 里收到 nextHopChainingCount(即 NCC):
这就是为什么 UE 必须本地维护整条 NH 链——它要随时能对齐网络指定的任意 NCC。
N2 切换时密钥由 AMF 直接算好下发:
sequenceDiagram
participant UE
participant Src as 源gNB
participant AMF
participant Tgt as 目标gNB
Src->>AMF: NGAP HANDOVER REQUIRED (含目标信息)
Note over AMF: AMF 用 K_AMF 推演出新 NH<br/>KgNB* = KDF(NH_n, PCI_tgt, ARFCN-DL)
AMF->>Tgt: NGAP HANDOVER REQUEST<br/>携带: KgNB* + NCC=n + 算法
Tgt-->>AMF: HANDOVER REQUEST ACK
Src->>UE: HO Command (含 NCC)
UE->>UE: 本地推演对齐NCC, 得到KgNB*
UE-->>Tgt: 接入目标
与 Xn 切换的区别:Xn 切换密钥由源 gNB 用储备 NH 算(消耗储备);N2 切换密钥由 AMF 用 K~AMF~ 直接算(不消耗 gNB 储备)。所以N2 切换天然有前向安全,而 Xn 切换的前向安全取决于源 gNB 是否还有未消耗的 NH 储备。
下图刻画 NCC 与 NH 储备的状态机:
stateDiagram-v2
[*] --> 初始: 注册完成, gNB持 KgNB(NCC=0) + NH储备(NCC=1)
初始 --> 水平HO1: 同频快速切换(水平)
note right of 水平HO1
NCC保持不变(=0)
NH储备(NCC=1)未消耗, 仍可用
无前向安全
end note
水平HO1 --> 水平HO2: 再次水平
初始 --> 垂直HO1: 关键切换(垂直)
note right of 垂直HO1
NCC +1 => 1
消耗NH储备
前向安全成立
但目标gNB现在无NH储备!
end note
垂直HO1 --> 等待补充NH: 需AMF经PathSwitch/ContextMod下发新NH(NCC=2)
等待补充NH --> 垂直HO2: 收到新NH后可再做垂直切换
实战含义:如果一个 UE 长时间停留在某个 gNB 上做了多次 Xn 水平切换,该 gNB 的 NH 储备(最初 NCC=1 那个)一直留着没用。一旦发生一次垂直切换,储备被耗尽,必须等 AMF 补充才能再有前向安全。AMF 补充的时机是 Path Switch Request Response 之后的 UE Context Modification 流程。
InitialContextSetupRequest / UEContextModificationRequest:其中的 Security Key 字段即下发给 gNB 的 KgNB;Next Hop Chaining Count 字段即 NCC,伴随 NH(在加密接口上不可见明文 NH,但 NCC 可见)。HandoverRequest:携带目标 gNB 的 KgNB*(Security Key)与 NextHopChainingCount。RRCReconfiguration → reconfigurationWithSync:含 nextHopChainingCount,这是 UE 判别水平/垂直的唯一依据。SecurityModeCommand:携带选定的 NAS 算法(NEA/NIA),驱动 A.8 派生 K~NAS*~。可借助 pcap-analyzer 这类工具直接对 NGAP/XnAP/RRC 报文做字段级解析,定位 NCC 是否对齐。
| 现象 | 可能根因(密钥相关) | 排错思路 |
|---|---|---|
| 切换后业务不通/掉话 | UE 与 gNB 的 NCC 不一致,导致派生 KgNB* 不同,完整性校验失败 | 检查 HO Command 中 NCC 与 UE 本地 NCC;查 AMF 是否正确滚动 NH |
| 切换后下行可解、上行乱码 | 算法列表协商不一致(NEA/NIA 选择不同) | 对比 SMC 中双边算法,确认 AS 算法优先级一致 |
| 频繁 Xn 切换后出现安全降级 | 多次水平推演,NH 储备耗尽未补充,后续切换无前向安全 | 检查 Path Switch 后 AMF 是否触发 Context Modification 补 NH |
| 注册后立即不通 | KgNB 推演输入的上行 NAS COUNT 双方不一致 | 确认注册流程 SMC 的 NAS COUNT 是否对齐 |
| DC 场景 SN 不可用 | KSN(A.16)派生或下发异常 | 检查 MN→SN 的 SgNB Addition 中密钥传递 |
| ## 九、近年演进:双连接、LTM 与 Key-change-on-the-fly |
这套机制在 R17/R18 持续扩展:
Q1: KgNB 和 K~AMF~ 到底谁推演出谁,方向是什么? A: K~AMF~ 是父,KgNB 是子。KgNB = KDF(K~AMF~, FC=0x15, 上行NAS COUNT)。AMF 和 UE 各自独立用相同的 K~AMF~ 和 NAS COUNT 推演出相同的 KgNB,然后 AMF 把 KgNB 下发给 gNB。gNB 反推不出 K~AMF~(KDF 单向)。
Q2: 水平推演和垂直推演的本质区别是什么?为什么一个有前向安全、一个没有? A: 水平用 KgNB(gNB 自己持有)派生下一跳,知道当前就能算未来;垂直用 NH(K~AMF~ 单向链上的一个值)派生,gNB 只握有当前一个 NH,要算下一个 NH 需要 K~AMF~(gNB 没有),所以被攻破的 gNB 算不出后续垂直切换的密钥,前向安全成立。
Q3: UE 是怎么知道该用水平还是垂直推演的?
A: 唯一依据是 RRCReconfiguration 中携带的 nextHopChainingCount(即 NCC)。UE 拿它和本地 NCC 比:相等则水平,更大则垂直(并先把本地 NH 链滚到该 NCC)。这也是 UE 必须本地维护完整 NH 链的原因。
Q4: 为什么 gNB 只拿到一个 NH,而不直接拿到整条链? A: 拿到整条链等于把前向安全拱手让出。规范刻意让 gNB 只持"一跳"的 NH 储备(NCC+1 那个),用完即空,必须等 AMF 经 Path Switch / Context Modification 补充。这是用"信息不对称"换取安全的设计。
Q5: Xn 切换和 N2 切换在密钥处理上有什么不同? A: Xn 切换密钥由源 gNB 用储备 NH 派生(消耗储备,前向安全取决于是否有 NH);N2 切换密钥由 AMF 用 K~AMF~ 直接派生(不消耗 gNB 储备,天然有前向安全)。这也是为什么 N2 切换虽信令更重但安全性更强。
本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵爱卫生(微信ID: gprshome201101)维护,聚焦5G/6G核心网、3GPP标准解读、通信前沿技术深度分析。 出版作品有《5G核心网原理与实践》《IMS原理与实践》等4本通信专业书籍。知识星球「51学通信」提供深度技术答疑和行业洞察。
[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。
