标题: 无线信号能被偷听吗?空口加密 作者: 爱卫生 封面: "[[封面1.png]]" 封面裁剪: false 原文地址: 打开评论: true 仅粉丝可评论: false 摘要: 先接受一个不舒服的事实:你手机发出的每一个比特,都以电磁波的形式在空气中向四面八方扩散。任何一个人,只要在几百米内架一根天线,就能把这段波形原原本本地录下来。这不是安全漏洞,这是无线电的物理本质——广播。
先接受一个不舒服的事实:你手机发出的每一个比特,都以电磁波的形式在空气中向四面八方扩散。任何一个人,只要在几百米内架一根天线,就能把这段波形原原本本地录下来。这不是安全漏洞,这是无线电的物理本质——广播。
蜂窝网络没有能力阻止别人“听”,就像广场上喊话没办法阻止路人驻足。它唯一能做的,是让听到的人听不懂。这就是机密性保护(Confidentiality Protection),俗称加密——本文的主角。
历史上确凿发生过的事是:2G时代的GSM空口加密算法A5/1,在2009年前后被安全研究者用彩虹表方式公开攻破,此后数年又出现了实时解密的演示。从那以后,“空口加密必须走现代密码学路线”成了整个行业铁律。3G重建了整套安全体系,4G/5G则在两套标准里把加密做成了强制能力——这套体系运转至今,你的通话、短信、微信消息在空气中始终以密文形态飞行。
这篇文章要讲清楚的就是这件事:一段明文数据,从手机发出到基站收到,中间的“暗语”是怎么造出来的、怎么对上号的、什么时候开始生效、又为什么偏偏有些部分故意不加密。
讲流密码之前,先看一个思想实验。
假设你要给朋友传一张纸条,希望绝对没人能看懂。办法是:准备一沓便签,每张上面写满完全随机的字符。你和朋友拿着一模一样的一沓。你把纸条每个字母和便签第一张上的字符逐个“混合”,得到密文;朋友拿同一张便签逐个“反混合”,还原出明文。每用掉一张便签就撕掉,绝不复用。
这就是香农在1949年证明的“一次一密”(One-Time Pad):只要密钥完全随机、和明文一样长、且绝不复用,这个密码体系在数学上是无懈可击的——敌人截获密文后,任何明文都有可能,他连猜都没法猜。
但一次一密在工程上根本不可用:它要求你预先分发和全部通信量等长的随机密钥。你今天要传2个G的视频,就得提前抱2个G的随机便签去找朋友。密钥分发量等于业务量,这不叫通信,这叫搬家。
实用化的思路是退一步:不追求完美的随机便签,改用一台“便签机”——一台由密码学家精心设计的机器,你塞进去一小段密钥(128位),它就能源源不断地吐出看起来完全随机的字符流。通信双方拿同一型号的机器、塞同一把钥匙,就能吐出一模一样的伪随机字符流。一方拿它加密,另一方拿它解密。
这就是流密码(Stream Cipher)的本质。空口加密选的就是这条路。
把上面的直觉画成图:
flowchart TD
K["128位密钥 K"] --> A1["发送端加密算法"]
P["COUNT等参数"] --> A1
A1 --> Z1["密钥流 Z"]
P1["明文数据 P"] --> X1["逐位异或"]
Z1 --> X1
X1 --> C["密文 C"]
C --> ANT1["发往空中"]
ANT1 --> ANT2["基站收到密文"]
ANT2 --> X2["逐位异或"]
C --> X2
K2["同一把密钥 K"] --> A2["接收端解密算法"]
P2["相同COUNT等参数"] --> A2
A2 --> Z2["同一串密钥流 Z"]
Z2 --> X2
X2 --> P3["还原明文 P"]
几个关键点拆开看:
第一,加密和解密是同一个动作。 流密码的加密运算就是逐位异或(XOR)。异或有个美妙的性质——可逆性:
$$C = P \oplus Z$$
$$P = C \oplus Z$$
密文等于明文异或密钥流;想还原,拿同一串密钥流再异或一次就回来了。一把函数两用,硬件上就是同一组门电路,加解密代价完全对称。对每秒要处理几十万比特的手机芯片来说,这个“便宜”至关重要。
第二,真正的机密全部押在密钥流上。 密文本身没有任何秘密——它天天在空气里飞。秘密在于:不知道密钥的人,就算录下了整段密文,也无法推出密钥流的下一个比特。密码学家的全部功力,都花在让这台“便签机”吐出的序列看起来随机、实际上可复现这一点上。
第三,两端的“便签机”必须逐比特对齐。 这是流密码最娇气的地方,也是后面调试故事的主角:发送端用第1000号位置的密钥流加密,接收端就必须用第1000号位置的密钥流来解。哪怕错开一个比特,后面解出来的全是乱码——就像抄写密电码时漏抄了一个字,从这个字往后整页全废。
那台“便签机”吐密钥流之前,需要喂进去几样配料。这不是设计者拍脑袋,每一味都有明确目的:
| 配料 | 说明 | 为什么需要它 |
|---|---|---|
| 密钥 K | 128位,来自认证后逐层派生 | 密码的根,只有通信双方持有 |
| COUNT | 32位计数器,随每个数据包递增 | 让每个包用不同的密钥流片段 |
| BEARER | 承载标识,区分不同业务流 | 电话流和上网流不能共用同一段密钥流 |
| DIRECTION | 方向位,区分上行/下行 | 防止上下行加密用同一段流互相“对冲” |
| LENGTH | 本次需要的密钥流长度 | 按需取用,够用即止 |
用公式把这台机器的形式化描述写出来:
$$Z = E_K(\text{COUNT},\ \text{BEARER},\ \text{DIRECTION},\ \text{LENGTH})$$
其中 $E_K$ 就是具体的加密算法(下节的三选一)。
配料表里最值得多看一眼的是COUNT。它解决的是一次一密工程化后最大的隐患:密钥流复用。如果两个数据包用同一把密钥生成了同一段密钥流,攻击者把两段密文异或一下,密钥流抵消,剩下的就是两段明文的异或——明文之间的统计关系立刻暴露,这是密码学上的灾难。COUNT让每个包在“密钥流长河”里取用不重叠的河段:第1个包取第1段,第2个包取第2段,只要COUNT不重复,密钥流就永不复用。同时COUNT还兼任防重放:重放一个旧包,接收端发现COUNT倒退,直接丢弃。
另外三项同样各有算计:不区分承载,攻击者可以拿电话密文和上网密文做交叉分析;不区分方向,同一位置的上行密文异或下行密文,密钥流也会互相抵消。这些参数本质上是把“一段密钥长河”切成了互不重叠的无数个子段,从根上杜绝任何形式的流复用。
3GPP为空口加密指定了几套算法,网络和手机在建立连接时协商选用哪一套。梳理成一张表:
| 算法编号 | 底层算法 | 出身 | 特点 |
|---|---|---|---|
| EEA0 / NEA0 | 空算法(不加密) | 3GPP规定 | 输出的密钥流全为零,异或等于没加 |
| EEA1 / NEA1 | SNOW 3G | 欧洲学术界与产业界 | 专为通信设计的流密码,软硬件实现都高效 |
| EEA2 / NEA2 | AES(计数器模式) | 美国NIST标准 | 借用AES的公信力,全球部署最广 |
| EEA3 / NEA3 | ZUC(祖冲之算法) | 中国科学院团队设计 | 中国密码算法首次进入国际移动通信标准 |
(EEA是4G时代的编号,NEA是5G沿用同一套底层算法后的重新编号,一一对应。)
三个型号里有两处值得驻足的故事。
第一处是AES的“入乡随俗”。 AES本身是分组密码——一次处理128位一块。但空口要的是流密码。工程上的办法是计数器(CTR)模式:把COUNT等参数当作计数器输入AES,生成一个128位的块,作为密钥流;计数器加一,再生成下一块……如此一来,分组密码被“改装”成了密钥流生成器。这印证了流密码与分组密码并非楚河汉界——分组密码套上计数器的外壳,就是一台流密码便签机。
第二处是祖冲之算法的登台。 2011年,由中国科学院数据与通信安全研究团队设计的ZUC算法,被3GPP接纳为4G空口的第三套加密与完整性算法,成为中国自主设计的密码算法第一次进入国际移动通信标准体系。算法以中国古代数学家祖冲之命名,内部以线性反馈移位寄存器为核心、配合非线性变换输出密钥流,属于典型的面向硬件流实现设计的通信密码。对做通信的中国工程师来说,这是日常在用的“国货”——只是绝大多数人没有意识到,自己每次扫码上网,背后跑的可能是祖冲之。
很多人以为加密就是把整封信塞进保险箱。实际上,4G/5G的空口加密刻意保留了一小块“明文区”——信封是裸奔的,只有信纸内容加密。
加密发生在PDCP层(无线协议栈里负责数据组装与安全的一层),加密的边界画得非常精确:
flowchart TD
IN["上层交来数据包"] --> H["生成PDCP头部<br/>序号等控制信息"]
IN --> D["数据载荷"]
D --> ENC["加密运算"]
K["加密密钥与参数"] --> ENC
H --> ASM["组装PDCP数据包"]
ENC --> ASM
ASM --> MI["尾部附上完整性校验码<br/>MAC-I 不加密"]
MI --> OUT["发往下层"]
三个区域三种待遇,每一处都是深思熟虑:
PDCP头不加密。 原因很实际:接收端解密之前,必须先从头里读出序号,才能拼出COUNT、才能定位密钥流的正确位置。头要是先加密了,就是“钥匙锁在保险箱里”的死循环——鸡生蛋问题无解。此外,下层做重排序、重复包检测也需要读明文头。
数据载荷加密。 这是用户的真实数据,是机密性保护的全部意义所在。
完整性校验码(MAC-I)不加密。 它是给接收端做“验货”用的印章,本身要被算法消费才能完成校验,把印章也加密等于让收件人先拆锁才能看到锁孔在哪。
顺带把两组常被混淆的概念分清楚。加密保护的是“不被看懂”,凭据是密钥;完整性保护(此前文章里那枚“火漆印”)保护的是“不被篡改”,凭据也是密钥但算法独立——所以你会看到两者是两个独立的开关、两个独立的算法编号(机密性EEA、完整性EIA),在建链时分别协商。扰码则完全不是安全机制:它用一段公开的、无密钥的伪随机序列对波形做随机化,目的是让信号统计特性更像噪声、减少相邻小区干扰,任何人都能解开。新手最常犯的错就是把“抓包看不到原始数据”当成“加密起效了”——不加密时你看到的往往只是扰码和调制后的形态,跟密码学毫无关系。
加密能力不是手机一开机就生效的。开机之初,最脆弱的几条消息——附着请求、鉴权消息——是以明文飞在空中的,此时网络和手机之间还在“用明文商量以后怎么说暗语”。这个交接过程叫安全模式建立,顺序设计极有讲究:
sequenceDiagram
participant U as 手机
participant G as 基站
U->>G: 初始接入消息(明文)
G->>U: 安全模式命令(先激活完整性保护)
U->>U: 校验命令消息真伪
U->>G: 安全模式完成(自这条起加密生效)
Note over U,G: 此后所有消息既盖章又加密
注意顺序:先激活完整性保护,后激活加密;而且手机回复的“安全模式完成”这条消息本身,就已经带着加密了——回复即密文,是加密生效的即时凭证。
为什么是这个顺序?直觉上有两层。其一,完整性保护是“验明正身”:手机要先确认发安全模式命令的真是真基站而不是钓鱼者,确认之后再接受对方指定的加密算法才安心——先验证裁判资格,再听裁判定规则。其二,从工程顺序看,验签只需要明文消息,而加密一旦开启就无法回头,先盖章后加密让整个握手过程每一步都可验证、可回退。标准层面只规定了这个先后次序,各设备厂的实现细节以其官方文档为准。
还有一个容易被忽略的细节:加密算法的协商是网络说了算。手机在能力上报里列出自己支持的算法清单,网络从中挑选一个,而不是双方讨价还价。这个设计的深意是:加密策略是网络运营者的安全策略,手机只能声明“我会什么”,无权决定“用什么”。
表格里那个EEA0常让人疑惑:都什么年代了,为什么标准还允许空算法?
几个现实原因。有些部署场景——早期物联网模块、某些专用网络——设备能力有限,强制加密会排除它们;一些紧急呼叫的极简实现路径也对处理时延有苛刻要求;另外,空算法还是一个“测试基准”:实验室调试加密功能时,先跑一遍EEA0确认链路本身通,再切换真算法,出了问题好定位是链路故障还是加解密故障。
但要认清一点:EEA0的存在是能力选项,不是安全建议。运营商现网配置里,商用网络的机密性策略普遍启用真算法。你在调试物联网专网时如果遇到EEA0,那是一道需要你显式确认风险的配置项,而不是可以顺手忽略的默认值。
流密码娇气在哪?两端密钥流必须逐比特对齐。对齐依赖COUNT一致,而COUNT由数据包头里的序号和接收端维护的超帧号两部分拼成。设备重启、异常释放、单板倒换之后,如果一端把超帧号丢了,两端对同一个包算出的COUNT就会错开——于是出现一种极具迷惑性的故障现象:
信号满格、链路通、完整性校验也偶尔能过,但数据就是解不开,表现为大量乱序丢弃或解码失败。
排查思路顺着本章原理走:既然密文在空中是好的,问题必然出在“两台便签机没吐同一段流”。先确认两端COUNT是否对齐(协议里超帧号有推断规则,正常情况收端能从序号加推断补全COUNT;异常释放和重建时推断就可能出现偏差),再看加密算法协商结果两端是否一致。经验上,“能收到但全错”与“压根收不到”是两类完全不同的故障域——前者十有八九是安全上下文没对齐,后者才是射频问题。
另一个实战要点:想抓到明文做业务定位,别在空口抓——那里永远是密文。合理的位置是加密终结点之后的网络侧接口,用户面数据在承载网里以明文GTP隧道封装传输,在那里可以拿到解密后的完整载荷。这也顺便回答了一个架构问题:空口加密只覆盖无线这一段,数据进入承载网和核心网后依靠的是传输层与网络内部的其他安全机制接力保护——安全是分段负责的,没有一段技术包打全程。
回望全文,空口加密的巧妙之处在于它对物理定律的臣服与利用:
它承认电磁波无法不广播,于是不阻止任何人“听”,只保证听到的是乱码;它承认密钥不能预先搬运,于是用128位密钥驱动便签机无限产出密钥流;它承认设备会失步、链路会重建,于是把密钥流的“地址”(COUNT)明文放在头上,让对齐永远可修复;它甚至承认世界上存在不需要加密的场景,于是保留EEA0作为选项却让策略决定权牢牢握在网络手里。
对1-3年经验的工程师,希望这篇文章留给你三样东西:一张流密码加解密对称性的原理图,一份“密钥流五配料”的参数直觉,以及一条调试铁律——空口故障先分清“收不到”和“解不开”,后者先查安全上下文对齐。
Q: 空口加密和扰码(scrambling)是一回事吗? A: 不是,而且是新手最典型的混淆。扰码用的是公开的、无密钥的伪随机序列,目的是随机化信号统计特性、压制小区间干扰,任何接收机都能解开,不具备任何保密性;加密用的是带密钥的算法输出,没有密钥在数学上不可还原。判断标准很简单:需要密钥的才是加密。
Q: 为什么空口偏爱流密码,而不是AES-CBC这类经典分组模式? A: 空口数据是小包、高频次、有损的流。流密码逐比特处理,无填充开销、时延确定、单比特错误不扩散——丢一个包不影响后面包的解密。有趣的是,EEA2选的恰恰是AES的计数器(CTR)模式,也就是把AES改装成密钥流生成器——所以更准确的说法是:空口需要的是“流密码化的处理方式”,至于密钥流由专用流密码还是分组密码改造而来,都可以。
Q: COUNT是32位的,用完了怎么办?密钥流会不会重复? A: 32位意味着约43亿个包内密钥流绝不复用,而正常业务远达不到这个量级;接近上限时协议要求触发密钥更新,刷新密钥后密钥流长河整体换源。工程中真正的麻烦不是“用完”,而是异常场景下两端COUNT失步——那是“解不开”类故障的头号嫌疑人。
Q: 打电话(VoNR/VoLTE)也走这套加密吗? A: 是。语音在空口段和上网数据走同样的PDCP安全机制,一视同仁地加密与完整性保护;语音数据真正的“特殊待遇”在QoS层面(专用承载、低时延调度),不在安全层面。所以窃听者截获空口语音,拿到的是密文——除非攻破密钥体系。
Q: 换了基站,加密要重来一遍吗? A: 不需要从鉴权重来。切换时密钥会在锚点密钥基础上重新派生出一把“这方水土的”接入层密钥,随切换消息交给目标基站,安全上下文无缝交接。这也是密钥分层体系的设计初衷——回顾此前讲过的“密钥家谱”:根密钥不动,树枝随移动而更新,前向安全性由此而来。
本文为原理科普,全部技术事实以3GPP公开标准与下列经典教材为准;因成文环境限制,未对网络来源逐一实时核验,细节表述以标准原文为最终依据。
本文由「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 等场景全覆盖。
![[知识星球二维码.png]]