<!-- title: 图解空口加密与完整性保护 -->

# 图解空口加密与完整性保护：数据上锁之外，还要贴封条

## 一、从寄快递说起：密封箱解决不了所有问题

想象你要给异地的朋友寄一份合同。你会做两件事：第一，把合同放进一个**上了锁的密封箱**，防止快递员或小偷偷看内容；第二，在箱子的封口处**贴一张防拆封条**，收件人只要看到封条完好，就知道中途没人打开过箱子偷改内容。

移动通信的空口安全，用的正是这个思路。手机和基站之间的一切数据——微信消息、网页、通话语音包、切换指令——都要经过完全开放的无线电波传播。任何一台天线就能截获这些电波，所以空口是整个移动网络里**最暴露的一段路**。工程师给这段路设计了两道核心防线：

- **加密（Ciphering）**：把明文变成密文，让偷听者看不懂，对应“密封箱”；
- **完整性保护（Integrity Protection）**：给每个报文附上一个防伪标签，让篡改者改不了，对应“防拆封条”。

在现网中，这两件事都发生在**PDCP层**（分组数据汇聚协议层），也就是用户面/信令面数据离开手机基带前的最后一站。这两道防线使用的密钥不同、算法实例不同，缺一不可。

## 二、为什么只有加密不够：三种攻击与三道防线

很多人（包括不少干了几年无线优化的工程师）有一个直觉误解：“数据加密了，空口就安全了。”这个理解是**不完整的**。加密只防“偷看”，不防“改动”，更不防“重发”。我们先把攻击面看清楚：

```mermaid
flowchart LR
    A["空口数据"] --> B["攻击者"]
    B -->|偷看| C["窃听 得到隐私"]
    B -->|篡改| D["伪造切换指令"]
    B -->|重放旧包| E["重复触发扣费"]
    C --> F["防线一 加密"]
    D --> G["防线二 完整性保护"]
    E --> H["防线三 COUNT序号"]
```

这里有个非常关键、也最容易被忽略的原理：**空口加密用的是流密码，而流密码天然“可延展”（malleable）**。

回顾加密公式：

$$C = P \oplus KS(KEY, COUNT, BEARER, DIRECTION)$$

其中 $P$ 是明文，$KS$ 是密码算法生成的密钥流，$C$ 是密文。异或运算有个数学性质：攻击者不需要知道密钥，只要把密文的某一位翻转，解密后明文的对应位**也会精确地翻转**。也就是说，一个懂信令格式的攻击者，虽然看不懂你的密文，却可以**精准地修改**它——比如把切换指令里的目标频点改掉，把“同意”改成“拒绝”。接收方解密后得到一个“格式完全合法、内容已被篡改”的报文，如果只做加密不校验完整性，它会把假指令当真执行。

这就是为什么标准要求**加密与完整性保护必须配套使用**：加密保证“看不懂”，完整性保护保证“改不动”，两者合起来才构成完整的机密性与完整性。

## 三、加密原理：一台按需出账的“一次性密码本”

### 3.1 流密码的直觉

学过密码学的读者知道“一次性密码本”（One-Time Pad）：拿一串和明文等长的真随机比特流，与明文异或，理论上不可破解。问题是真随机密钥流太长，没法提前分发。

移动通信的解法非常聪明：**双方不保存密钥流本身，而是各自保存一把短的密钥（128位），需要时用相同的密码算法“现场生成”密钥流**。就像一本可以随时按需打印的密码本，只要两边的打印规则和起始页码一致，打出来的内容就一模一样。

```mermaid
flowchart LR
    K["KEY 密钥"] --> G["密钥流生成器"]
    C["COUNT 序号"] --> G
    B["BEARER 承载号"] --> G
    D["DIRECTION 方向"] --> G
    G -->|KS 密钥流| X{"异或"}
    P["明文P"] --> X
    X --> O["密文C"]
```

### 3.2 密钥流生成的“五要素”

密钥流不是只由密钥决定的。空口密码算法的输入参数及其设计意图如下：

| 输入参数 | 含义 | 为什么必须要它 |
|---|---|---|
| KEY | 128位加密密钥 | 核心秘密，来自认证后逐级推导的密钥体系 |
| COUNT | 32位报文计数器 | 保证每个报文用不同的密钥流段 |
| BEARER | 无线承载编号 | 保证不同承载的密钥流互不相同 |
| DIRECTION | 传输方向（上/下行） | 保证上行和下行密钥流互不相同 |
| LENGTH | 请求的密钥流长度 | 按明文长度精确出流 |

注意，除了KEY以外的四个参数都是**公开信息**，它们不负责保密，只负责**让密钥流永不重复**。为什么这一点如此重要？因为密钥流重复使用是流密码的死刑判决。假设两个明文 $P_1$、$P_2$ 用了同一段密钥流 $KS$ 加密：

$$C_1 \oplus C_2 = (P_1 \oplus KS) \oplus (P_2 \oplus KS) = P_1 \oplus P_2$$

密钥流被彻底消掉了！攻击者拿到两段密文的异或，就等于拿到两段明文的异或，用词频分析很快能还原出内容。这就是著名的“二次密码本”问题。

所以标准才设计了BEARER和DIRECTION这两个参数：手机有多个无线承载（信令承载、多个数据承载），上行下行同时收发，**每一条独立的“逻辑管道”都有自己专属的密钥流序列**，从根上杜绝重复。这体现了安全协议设计的一条铁律：不要指望人不出错，要用结构保证错误不可能发生。

## 四、完整性保护：一个算出来的“防伪章”

完整性保护的本质是一个带密钥的报文摘要，业界统称为MAC（Message Authentication Code）。空口上它长这样：

$$MACI = f(KEY_{int}, COUNT, BEARER, DIRECTION, MESSAGE)$$

发送方把整个报文（连同COUNT等公开参数）喂进完整性算法，吐出一个32位的标签MAC-I，附在PDCP报文尾部。接收方用同样的输入**独立重算**一遍，得到XMAC-I，逐位比对：

- **一致**：报文确实来自持有密钥的合法对端，且一个比特都没被改过——因为只要报文有任何一位变化，算出的MAC就完全不同（雪崩效应）；
- **不一致**：报文被篡改、伪造，或者收发双方密钥/计数器失步——直接丢弃。

要特别注意一个常见误解：**MAC-I不是加密的**。它不隐藏任何内容，只是一个“算出来的指纹”。它的安全性完全依赖那把只有收发双方才有的完整性密钥——攻击者没有密钥，即使能改报文，也算不出篡改后报文对应的合法MAC-I。

收发双方的完整处理流水线如下：

```mermaid
flowchart TB
    subgraph TX ["发送方PDCP"]
        A["明文报文"] --> B["计算MAC-I"]
        B --> C["报文附MAC-I尾部"]
        C --> D["异或密钥流加密"]
        D --> E["空口发送"]
    end
    subgraph RX ["接收方PDCP"]
        F["收到密文"] --> G["重算XMAC-I并比对"]
        G -->|一致| H["解密交付上层"]
        G -->|不一致或COUNT过期| I["丢弃并触发失步处理"]
    end
    E --> F
```

注意流水线的顺序细节：**发送方先算MAC、再加密**（MAC用明文计算）；**接收方先校验MAC、再解密**。这个顺序保证了完整性校验直接作用于空中真实传输的密文，密文本身也在被保护之列。

## 五、COUNT：防重放的序号，也是密钥刷新的闹钟

COUNT是一个32位计数器，由两部分拼接而成：高位是超帧号HFN，低位是PDCP序列号SN（在5G中SN长度可配置，常见12/15/18位）。它在安全体系里承担两个职责。

**职责一：防重放。**攻击者录下一段合法报文（比如一条“开通某服务”的指令），原封不动地稍后重发——报文内容合法、MAC-I也合法，因为它是真的。防御手段就是COUNT：每发送一个报文，COUNT加一；接收方维护一个接收窗口，**只接受COUNT单调递增、落在窗口内的报文**。旧报文的COUNT早已“过时”，重放会被直接识别并丢弃。

**职责二：给密钥定寿命。**COUNT总有一天要走完32位空间。一旦回绕，同样的（KEY, COUNT, BEARER, DIRECTION）组合就会再次出现，密钥流开始重复——这就踩中了3.2节说的二次密码本红线。所以标准规定：**在COUNT即将回绕之前，必须触发密钥刷新**，双方换一把新密钥继续，相当于给密钥设了一个“使用寿命闹钟”。

## 六、算法家族：欧洲、美国、中国各出一名选手

空口加解密和完整性保护各有一组算法，5G沿用与4G同源的128位算法家族：

| 算法 | 用途 | 核心算法 | 出身 |
|---|---|---|---|
| NEA1 / NIA1 | 加密 / 完整性 | SNOW 3G | 欧洲ETSI安全算法组设计，线性反馈移位寄存器结构 |
| NEA2 / NIA2 | 加密 / 完整性 | AES | 美国NIST标准，此处以计数器模式出密钥流、以CMAC出MAC |
| NEA3 / NIA3 | 加密 / 完整性 | ZUC（祖冲之） | 中国自主设计，后进入国际标准体系 |
| EEA0 / NIA0 | 空算法 | 无 | 不加密不保护，仅允许用于未经鉴权的紧急呼叫 |

几个值得咀嚼的点：

- **三套算法功能等价，可协商选择**。注册时网络通过安全模式命令下发自己选择的算法，终端声明自己支持哪些。主流实现里AES因为芯片普遍有硬件加速，性能最好；SNOW 3G和ZUC是纯软件友好的流密码结构。
- **祖冲之算法（ZUC）是中国密码界的高光时刻**：它以线性反馈移位寄存器加非线性有限状态机的结构实现，名字取自中国古代数学家，经过国际密码学界的公开评估后成为国际标准算法，这是国产密码算法进入国际移动通信体系的标志性事件。
- **空算法的存在是个“必要的恶”**：紧急呼叫（如110）要求“无卡、未鉴权也能打”，此时没有密钥可言，只能放行不保护的报文。正因为它危险，标准把它的使用场景收得极窄。

## 七、4G到5G：最重要的变化是用户面也贴封条了

| 对比项 | 4G LTE | 5G NR |
|---|---|---|
| RRC信令完整性保护 | 强制 | 强制 |
| 用户面完整性保护 | **不支持**，数据只加密 | **可选开启**，按承载逐个协商 |
| 用户面加密 | 强制（除紧急呼叫） | 强制（除紧急呼叫） |
| 空口用户标识 | IMSI可能明文暴露 | 默认用SUCI隐藏后的标识 |
| 算法家族 | SNOW 3G / AES / ZUC | 相同家族，128位 |

4G时代有一个常被忽视的安全短板：用户面数据**只加密、不做完整性保护**。加密的“可延展性”意味着理论上存在定向篡改数据的可能，只是攻击者需要相当强的空口注入能力。到了5G，工业互联网、车联网、电网差动保护等业务走进蜂窝网络，这些业务承载的是**指令**而非“内容”，篡改的危害远大于窃听。于是5G引入了用户面完整性保护能力，可以按承载开启。

那为什么默认常常不开？两个成本：每个报文要多携带4字节的MAC-I，且完整性计算比异或加密更耗算力；同时终端侧的标准基线只要求支持较低速率的用户面完整性保护（量级在每承载几十kbps），跑大流量业务时普遍还是“只加密”。所以它的定位是**给敏感小数据业务（IoT指令、遥测、控制信令类）提供的精细选项**，而不是全网强推。

## 八、安全激活：封条什么时候才贴上

还有一个容易踩坑的时序问题：手机开机注册时，最先交互的几条消息是**明文**的——因为没有密钥可用，加密和完整性保护要等到网络完成鉴权、推导出各层密钥之后，通过**安全模式命令（Security Mode Command）**显式激活：

```mermaid
sequenceDiagram
    participant U as 手机
    participant N as 基站
    Note over U,N: 鉴权已完成 双方持有根密钥
    N->>U: 安全模式命令 指定完整性算法与加密算法
    U->>U: 校验该命令本身 生成各层专用密钥
    alt 算法均支持
        U->>N: 安全模式完成 自此报文贴MAC-I并加密
        N->>N: 双侧激活加密与完整性校验
    else 算法不支持
        U->>N: 安全模式失败 连接重建或释放
    end
```

对工程师来说，这个流程有非常直接的实战价值：

- **抓空口信令时**（测试UE、协议分析仪），安全模式命令**之前**的消息是明文可读的，**之后**全部变成密文。想在空口看到某条NAS消息的内容，要清楚它是否发生在安全激活之前。
- **安全模式失败**是现网常见故障，根因多数不是“算法坏”，而是**终端不支持网络下发的算法组合**，或者**密钥失步**——双方手里根本没有同一把根密钥。
- **MAC-I校验失败的典型表现**是报文被静默丢弃、信令无响应、随后无线链路重建。排查方向优先看密钥是否失步（比如切换或重建过程中密钥没有正确刷新、COUNT没有延续），而不是怀疑算法本身。
- **COUNT失步**（比如数据长时间中断后SN对不上）会触发PDCP丢弃或重建，在做模组调试、看PDCP状态报告时，两端的TX/RX COUNT是首要比对项。
- **两个高频误解**：其一，“开了加密就不用管完整性”——错，流密码可延展，篡改可绕过加密；其二，“MAC-I是加密的校验码”——错，它不保密任何东西，只是防伪指纹。

## 常见问题

**Q1：加密和完整性保护能只开一个吗？**
A：技术上算法独立，但标准要求信令两者配套。只开加密的后果是“看不懂但改得动”——攻击者可利用流密码的可延展性精准翻转比特；只开完整性的后果是内容裸奔。用户面数据在4G只开加密是历史遗留短板，5G已可补齐。

**Q2：MAC-I校验用的密钥和加密密钥是同一把吗？**
A：不是。安全体系中完整性密钥与加密密钥是从上层密钥分别推导出来的独立密钥，算法实例也独立。这种“密钥分离”保证即使一个环节出问题，另一道防线不受牵连。

**Q3：为什么不同承载、上下行要用不同的密钥流？**
A：流密码密钥流一旦重复，两段密文异或就能消掉密钥流、暴露明文关系。BEARER、DIRECTION、COUNT三个公开参数进入密钥流生成器，就是用结构性手段保证每一段密钥流在全网、全时空只出现一次。

**Q4：重放攻击靠什么防御？是时间戳吗？**
A：不是时间戳，是COUNT计数器加接收窗口。每个受保护报文的COUNT严格单调递增，重放的旧报文COUNT必然落后于接收窗口，直接被判死。COUNT同时还是密钥寿命指示器——回绕前必须换钥。

**Q5：SNOW 3G、AES、ZUC该怎么选？**
A：功能上等价、安全强度上都被国际密码界认可，选择主要看实现条件：有硬件AES加速的芯片选NEA2/NIA2性能最优；纯软件实现时SNOW 3G与ZUC的流密码结构更轻量。现网中由网络在安全模式命令里指定，终端不支持就会触发安全模式失败。

## 参考来源

3. [ShareTechnote - PDCP Handbook](https://www.sharetechnote.com/html/Handbook_PDCP.html) — PDCP层功能、COUNT构成与安全处理的工程师视角总结
5. 经典教材《通信原理》《5G无线网络设计与实践》中关于流密码、MAC与移动通信安全体系的章节思路

---
> 本文由「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 等场景全覆盖。

![51学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
