空口加密技术:LTE/NR空口加密算法与密钥派生
空口加密,说白了就是给无线信号加一把锁。我刚开始做基站安全测试时,总觉得这层加密可有可无——反正信号在空中飘着,谁能截获?后来在一次运营商现网测试中,我亲眼看到用一台普通笔记本配合USRP,就能把未加密的语音包抓得清清楚楚。嗯,从那以后我再也不敢小看空口加密了。
为什么需要空口加密?
无线信号是广播的。你想想看,手机发出去的数据,基站能收到,旁边的人用个频谱仪也能收到。如果没有加密,你的通话内容、短信、上网记录,全都在空中裸奔。
我遇到过最典型的场景:某省运营商做安全审计,发现一个4G基站覆盖的工业园区里,有人用伪基站设备在抓用户IMSI。幸好当时启用了空口加密,用户数据虽然被抓到了,但解不开。要是没加密,那批用户的通信内容就全泄露了。
核心要点:空口加密保护的是用户面数据和控制面信令。加密后,即使攻击者截获了空口数据包,也无法还原出原始内容。
LTE/NR支持的加密算法
3GPP标准定义了三种核心加密算法。我按自己的习惯,把它们分成三类:
| 算法 | 类型 | 密钥长度 | 应用场景 |
|---|---|---|---|
| AES (128-EEA2) | 分组密码 | 128位 | LTE/NR通用,最广泛 |
| SNOW 3G (128-EEA1) | 流密码 | 128位 | LTE早期部署,向后兼容 |
| ZUC (128-EEA3) | 流密码 | 128位 | 中国自主算法,NR可选 |
这三种算法,说白了都是128位密钥。但它们的实现方式和性能特点差别很大。
AES算法:最稳的选择
AES是分组密码,工作在CTR模式下。我个人的经验是,AES在基站侧实现最成熟,硬件加速器几乎标配。你在商用基站里看到的加密模块,十有八九是AES。
为什么?因为AES的硬件IP核到处都是,芯片厂商直接集成好了。你写代码时只需要调用API,不用自己实现算法逻辑。
我的建议:如果项目没有特殊要求,优先选AES。兼容性最好,性能也够用。我在一个NR小基站项目里,用AES-128跑满100Mbps用户面流量,CPU占用不到5%。
SNOW 3G:老将出马
SNOW 3G是流密码,最早用在3G UMTS里。LTE继承了它。说实话,现在新部署的基站很少用SNOW 3G了。但如果你做的是存量基站升级改造,就得支持它——因为有些老终端只认这个算法。
我记得有一次,某地运营商做4G网络优化,发现一批物联网模组只支持SNOW 3G。基站侧如果没开这个算法,那些模组就驻留不了网络。最后我们不得不把SNOW 3G加上去。
注意:SNOW 3G的密钥流生成速度比AES慢。在高吞吐场景下,可能会成为瓶颈。我曾经测试过,纯软件实现SNOW 3G,单核只能跑到200Mbps左右。AES能跑到500Mbps+。
ZUC算法:国产之光
ZUC是中国自主设计的流密码,由中国科学院等单位研发。它在NR里被列为可选算法。说实话,ZUC的数学设计很精巧,安全性经过国内外密码学家的反复验证。
但实际部署中,ZUC的普及率不如AES。原因很简单:国外芯片厂商的硬件加速器很少集成ZUC。你要用ZUC,多半得靠软件实现。
我在一个国产化基站项目里用过ZUC。当时客户要求全链路国产密码算法。我们用了ZUC做空口加密,配合SM系列算法做传输层加密。性能嘛,软件实现大概能跑到150Mbps,够用。
加密密钥的派生过程
密钥不是直接用的。3GPP定义了一套完整的密钥派生体系。我画个简化的流程:
K (根密钥,存在USIM和HLR/HSS中)
|
v
CK, IK (通过AKA认证生成)
|
v
KASME (MME/HSS通过CK, IK派生)
|
+--> KeNB (基站密钥,用于空口加密)
| |
| v
| KUPenc (用户面加密密钥)
| KRRCenc (RRC信令加密密钥)
| KRRCint (RRC完整性保护密钥)
|
+--> KNASenc (NAS加密密钥)
+--> KNASint (NAS完整性密钥)
你想想看,这个派生链有多长。从根密钥K开始,经过AKA、KASME、KeNB,最后才到空口加密密钥。每一层都用了不同的密钥派生函数(KDF)。
为什么要这么复杂?
说白了,就是隔离风险。如果空口密钥被破解了,攻击者只能拿到当前会话的数据。根密钥K还在USIM卡里,安全得很。基站侧泄露了KeNB,也影响不到核心网。
密钥派生中的关键参数
实际派生时,需要输入一些参数。我列一下常用的:
- NAS uplink COUNT:NAS层计数器,防止重放攻击
- Bearer ID:承载标识,区分不同数据流
- Direction:上行/下行方向标识
- Algorithm ID:使用的加密算法标识
这些参数组合起来,确保每个会话、每个承载、每个方向的密钥都不同。我在做安全审计时,经常检查这些参数有没有正确传递。曾经发现一个基站实现里,Direction参数写死了0,导致上下行用了同一个密钥。嗯,这算是个低级错误。
实际部署中的避坑指南
我踩过不少坑,挑几个典型的说说:
我曾经犯过的错:
- 密钥派生时,COUNT值没有及时更新。结果重附着后,新会话用了旧密钥。攻击者只要抓一次包,就能一直解密。
- 算法优先级配置错误。基站侧把ZUC排在最前面,但终端不支持。导致反复协商失败,用户无法接入。
- 完整性保护没开。只加密不校验完整性,攻击者可以篡改加密后的数据包。虽然解不开内容,但能破坏通信。
我的建议:
- 密钥派生函数(KDF)一定要用标准实现。别自己写,容易出漏洞。
- 算法协商时,按AES > ZUC > SNOW 3G的顺序配置。兼容性最好。
- 完整性保护和加密必须同时启用。缺一个都不安全。
性能优化小技巧
空口加密对实时性要求很高。我分享几个优化经验:
- 预计算密钥流:对于流密码(SNOW 3G、ZUC),可以提前生成一段密钥流缓存起来。数据来了直接异或,省去实时计算的时间。
- 硬件加速:如果芯片支持AES-NI指令集,一定要用。性能提升5-10倍。
- 多核并行:不同用户的数据流可以分配到不同核上加密。我做过测试,4核并行处理,吞吐量能提升3.5倍左右。
嗯,空口加密这块内容不少。但核心就三点:选对算法、派好密钥、做好优化。你只要把这三点拿捏住,基站空口安全这块基本就稳了。