简介:面向 GSM 网络优化、移动通信安全及密码学方向的学习者,这份中文 PDF 系统梳理了 A3、A5、A8 三种算法的设计定位与执行流程,并以挑战响应机制、RAND/Ki/SRES/Kc 生成链路为主线,把用户鉴权、数据加密、密钥派生之间的协作关系拆解清楚,适合对照 3GPP 文档或课程讲义查漏补缺。压缩包仅含 1 个 PDF 文件,大小约 310KB,内容紧凑,便于随时翻阅。目前已有 245 人学习下载。资料从 GSM 安全机制分布切入,依次介绍 SIM 卡、基站子系统与网络子系统的安全职责,并结合算法流程图和具体步骤说明,帮助读者理解 A5/1、A5/2、A5/3 等版本差异与后续演进方向。对备考移动通信课程、撰写网络协议报告或做安全机制对比的读者,是可直接参考的中文资料。
1. 从GSM说起:A3/A5/A8到底在系统里扮演什么角色
GSM作为第二代移动通信标准,从诞生那天起就不是“裸奔”的。它内置了一套完整的安全机制,目的很单纯:确认手机里的SIM卡是合法的,同时让空口传输的内容不被别人听走。这套机制由三个算法分工完成,就是很多人挂在嘴边却不一定搞透彻的A3、A5、A8。
先说结论,这三个算法各干各的活:A3负责“身份认证”,也就是手机证明自己是自己;A8负责“生成密钥”,给后续加密提供一把会话密钥;A5负责“空口加密”,把语音和用户数据真正地打乱。它们不是三个独立的冷冰冰的公式,而是被设计成一张相互咬合的齿轮组,合在一起才构成GSM的安全闭环。
我最早接触这三个算法,是在做无线空口协议分析项目的时候。当时的任务很简单:通过抓取空口信号,反推设备在做认证时到底交换了什么信息。结果发现,很多文档只告诉你“A3A5A8”这五个字符,但真正落地时细节极多,网上一搜全是零散资料,很少有文章把完整过程讲清楚。所以这篇就当是把我踩过的坑、翻过的文档、亲手复现过的流程整理成一份可参考的笔记,给做通信安全、协议分析或嵌入式开发的朋友省点时间。
2. A3算法拆解:手机和网络怎么“对暗号”
2.1 A3的输入与输出不是你想的那样
很多人以为A3就是一个输入、一个输出的简单映射,实际上A3在GSM标准中的定义很抽象,它只规定了输入输出接口和流程,没有规定具体算法。当年运营商和设备商可以自己实现,最常见的是COMP128。
A3的输入是两个固定长度的参数:
- RAND:128位随机数,由网络侧(AuC,认证中心)生成,每次认证都不同
- Ki:128位密钥,存在SIM卡里,同时网络侧也有对应副本,这是“对暗号”的前提
输出只有一个:SRES(Signed Response),32位签名响应。手机用Ki和RAND算出SRES后返回给网络。网络侧在本地用同样的RAND和Ki算一遍SRES,如果和自己算的结果一致,就认定这张SIM卡合法。
这里有个很多人忽略的细节:A3在COMP128实现中,并不是单独算出一个32位的SRES就完事了。它内部会经过一个完整的混合运算,并且在运算过程中还会产生一个54位的中间量,这个中间量经过特殊处理会变成64位的Kc,也就是A8算法的输出。所以在工程实现里,A3和A8经常是“一次调用,两个结果”,而不是分开跑的。
2.2 COMP128的内部运算过程
COMP128这个实现值得单独拿出来说,因为它是当年应用最广的A3/A8实现方案。网上能找到泄露的C代码,结构不算复杂,但里面有几个设计点非常关键:
- 把Ki(128位)和RAND(128位)拼接成一个256位的输入
- 经过8轮重复运算,每轮包含查表、异或、压缩
- 内部有5张查找表T1到T5,用于非线性变换
- 每轮运算会把128位状态压缩到64位,8轮之后得到最终结果
具体每一步,可以这样理解:先把256位输入分成两半,各自经过T1表变换,然后异或合并,再经过T2表、压缩异或,逐轮迭代。最后输出时,取特定位置的32位作为SRES、54位作为Kc,再补上10个0凑成64位。
我在复现这个流程时发现,COMP128最容易被攻击的点就是查表结构。它本质上是一个基于查找表的8轮迭代,轮数不多,非线性层也不够复杂。后来的研究团队在1998年就找到了利用碰撞恢复Ki的方法:通过选择特定的RAND并观察SRES是否碰撞,就可以逐步缩小Ki的搜索空间,最终完整恢复出SIM卡的Ki。这也是为什么COMP128后来被COMP128-2、COMP128-3取代的原因。
2.3 A3认证的完整流程
实际的认证流程在《GSM 11.11》和《GSM 03.20》里有明确规定,大致分四步:
- 手机开机或位置更新时,向网络请求接入
- 网络下发一个RAND到手机
- 手机里的SIM卡执行A3运算,返回SRES给网络
- 网络比对SRES,一致则认证通过,允许接入
这个过程中,RAND是明文传输的,SRES也是明文传输的。也就是说,如果攻击者截获了一次认证的RAND和SRES,他只能拿到这一对数据,没法直接还原Ki,除非他破解的是COMP128本身。这也是为什么认证协议本身设计得足够好的话,即使在没有加密的情况下也不算太危险,真正危险的是实现算法的强度不足。
3. A8算法:会话密钥是怎么“现用现算”出来的
3.1 A8的定位:给加密“配钥匙”
A8的角色很清晰:为A5算法生成一把64位的会话密钥Kc。会话密钥这个词是重点。GSM体系没有用Ki直接加密用户数据,而是用Ki配合RAND算出Kc,再用Kc加密通话内容。这么做的一个朴素逻辑是:Ki是长期驻留在SIM卡里的,如果每次都直接用Ki加密,攻击者可以通过大量密文分析来反向推断Ki。而Kc是一次性的、每次认证都不同,泄露了也只影响当次通话。
A8的输入输出定义如下:
- 输入:RAND(128位)+ Ki(128位)
- 输出:Kc(64位)
注意,A3和A8的输入完全一样。这就是为什么COMP128能一次同时算出SRES和Kc的原因。设计者希望认证和密钥生成可以复用一套设备,减少SIM卡内的计算量。
3.2 Kc的生成细节
在COMP128实现中,Kc不是直接作为最终输出现成的,而是要经过一个“位移位”处理。COMP128的第8轮运算后会得到一个128位中间结果,其中特定区间的54位被提取出来,然后经过比特重排和补零,最终形成64位的Kc。
这54位补到64位的过程,涉及一个固定映射表。我第一次看的时候觉得很奇怪:为什么不直接输出64位,要拿54位再补?查了资料才知道,这是当年GSM标准的历史细节,为了让Kc符合某些国家的出口管制要求,故意让有效密钥长度变成54位,补10个0。这个操作极大地削弱了加密强度。从工程角度看,这是典型的合规需求削弱安全性的案例。
实际项目里,我一般会做一个Kc检查工具:拿到RAND和Ki之后,分别用COMP128、COMP128-2、COMP128-3算出Kc,对比SIM卡和网络侧记录的Kc是否一致,以确认SIM卡使用的是哪个版本算法。这在做设备兼容性测试时非常管用。
4. A5算法全解析:终于到了加密的“正主”
4.1 A5家族:A5/1、A5/2、A5/3的区别
A5算法负责加密用户数据,它有三个主要分支:
- A5/1:早期GSM用的强加密算法,主要在欧洲和大部分地区部署
- A5/2:出于出口管制设计的“弱化版”,主要出口到部分国家,安全性很弱
- A5/3:基于KASUMI分组密码的算法,用于3G和部分GSM升级场景,安全性高很多
A5/1和A5/2都属于流密码,核心是LFSR(线性反馈移位寄存器)结构。理解A5,本质上就是理解LFSR如何生成密钥流,以及密钥流如何和明文异或。
流密码的关键点在于:它不是把整个数据块一股脑加密,而是逐个比特生成密钥流,每个比特的明文和对应密钥流比特异或得到密文。解密时用同样的密钥流再异或一次就还原。A5/1做的就是这件事——用一个64位的Kc和22位的帧号,为每一帧生成228比特密钥流。
4.2 A5/1的内部结构:三个寄存器加“多数表决”
A5/1由三个LFSR组成,长度分别是19位、22位、23位,总长度玄机很大:64位Kc被平均分给三个寄存器做初态,但这三个寄存器长度加起来是64位(19+22+23=64),所以Kc的每一位都被用了。
三个寄存器的线性反馈多项式分别是:
- 寄存器X(19位):X[18], X[17], X[16], X[13]参与反馈
- 寄存器Y(22位):Y[21], Y[20], Y[16], Y[12]参与反馈
- 寄存器Z(23位):Z[22], Z[21], Z[18], Z[15]参与反馈
每个寄存器内部按多项式进行线性反馈,当一个寄存器被时钟驱动时,它内部的比特向右移动,新的最高位由反馈多项式计算得到。
A5/1最精妙的设计是时钟控制,它不采用“每个周期所有寄存器都动”的同步方式,而是采用一个多数表决机制:
- 每个寄存器取一个钟控位:X的第8位、Y的第10位、Z的第10位
- 三个钟控位中,多数为1的位所在的那几个寄存器被时钟驱动
- 例如X[8]=0, Y[10]=1, Z[10]=1,则多数是1(两个1),Y和Z被驱动,X不被驱动
这个机制的目的是制造非线性,让攻击者无法简单通过线性代数求解密钥。多数表决本身很简单,但它能让三个寄存器的运行变得错落有致,从而极大增加破解难度。
4.3 A5/1的初始化:Kc和帧号怎么“混”进去
A5/1的初始化过程是很多人容易搞混的地方。我自己第一次复现时也在这里绕了不少弯,误以为直接把Kc塞进寄存器就开始输出密钥流了。实际分两个阶段:
第一步:装载密钥和帧号。把64位Kc的每一位依次与三个寄存器的全部位异或(对寄存器X、Y、Z的所有位置依次执行),然后把22位帧号也依次异或进去。整个过程不输出任何密钥流,寄存器只是被不断搅动。
第二步:空转100拍。装载完成后,三个寄存器在没有任何输出的情况下继续被时钟驱动100个周期。这100拍的目的是让Kc和帧号充分混合,抹平Kc高低位之间的相关性。等到100拍结束,才进入真正的密钥流生成阶段。
密钥流生成阶段:每个时钟周期,三个寄存器各自输出最高位(X[18]、Y[21]、Z[22]),把这三个比特异或得到1比特密钥流。每帧需要228比特密钥流,所以这个阶段要跑228拍。
这里要特别强调的是同行链路方向性。GSM的每一帧是4.615毫秒,包含两个方向:上行(手机到基站)和下行(基站到手机)。A5/1在一个帧里给上行生成114比特,下行生成114比特,合计228比特。实现时,上行的密钥流和下行密钥流生成顺序是明确规定的:先生成下行的114比特,再生成上行的114比特。如果你在实现A5加密时,上行和下行搞反了,那解密永远对不上。
5. 一次完整呼叫里的安全流程:A3/A5/A8怎么配合
很多教材把A3、A5、A8分开介绍,看得懂每个细节,但组装不到一起。我拿一次真实呼叫流程来串一遍,从手机开机到通话建立,讲清楚这些算法到底在哪个环节发挥作用。
- 手机开机,SIM卡上电,手机向基站发接入请求
- 网络产生一个随机数RAND,下发给手机
- 手机把RAND传给SIM卡,SIM卡执行COMP128(同时运行A3和A8),得到SRES和Kc
- 手机把SRES发回网络,网络用相同的RAND和Ki算SRES,匹配成功则认证通过
- Kc被保存在手机和网络的加密单元里,等待加密模式建立
- 网络下发加密模式指令,手机和网络开始用Kc初始化A5算法
- 语音数据按帧传输,每帧用Kc和帧号初始化A5,生成228比特密钥流
- 上行和下行分别用各自的密钥流对语音帧进行异或加密/解密
你会发现,A3和A8在时间上几乎同时发生,Kc可以说是A3认证过程的一个“副产品”,但它是整个通话保密的核心。A5真正的启动时间则略晚一步,必须在认证成功之后才开始,否则网络就无法确认通信对象的身份。
这套流程在GSM时期存在一个实际痛点:它只认证了手机里的SIM卡,却没有认证网络。也就是说,攻击者可以伪造一个基站,下发一个RAND,拿到手机返回的SRES,然后离线破解Ki。这个中间人攻击的根源就是GSM安全体系里“单向认证”的设计缺陷,在后面推动3G/4G安全架构演进时,专门加入了双向认证机制。
6. 常见问题与排查技巧实录
6.1 为什么A5/2一夜之间变成废柴
A5/2是当年为了出口管制专门设计的弱化版,结构上和A5/1差不多,但多加了一个12位寄存器来控制时钟。多这个寄存器不仅没有增强安全性,反而让密钥流的生成产生了严重的统计偏差。2000年,Ian Goldberg等人发现A5/2可以在极短的已知明文条件下直接破解,不需要穷举Kc。
当时我在一个测试环境里复现了这个攻击。大概流程是:抓取一条已知明文对应的密文,建立若干方程求解线性反馈关系,再用高斯消元法还原寄存器初态。整个过程在当时的PC上用几个小时就能完成。这个案例告诉我们一个道理:安全强度不是靠“看起来复杂”实现的,A5/2的钟控逻辑复杂到连设计者都没预料到会引入统计泄露。
6.2 A5/1被“彩虹表”打穿
A5/1在很长一段时间被当作“安全”的代名词,但它的声明周期在2009年被彻底终结。当年的破解思路采用了时间-内存权衡攻击:预先计算大量A5/1的密钥流序列,建立彩虹表,然后在攻击时通过观察到的2分钟已知明文来快速匹配,恢复Kc。
我梳理一下这一攻击的关键点:它利用的是A5/1密钥流对Kc的强依赖性和有限状态空间。虽然三寄存器总共有2^64种初态,但并不是所有初态都可达,实际可能状态数比理论值小很多。彩虹表把大量的“状态-密钥流”对预先算好,查询时就能节省攻击时间。最终结果是,一些研究团队在几分钟内就能恢复Kc。GSM安全被彻底击穿,这也是后来GSM网络大规模升级到3G/4G,并且把A5/3纳入标准的重要原因。
6.3 实操避坑:复现A5算法时的常见错误
我自己用C语言和Python分别实现过A5/1,踩过的坑记录如下,供后来者参考:
- 位序搞反。不同文档对LFSR的“最高位”定义有差异,建议先在代码里明确bit0是最低位还是最高位,然后自测一帧128比特数据。
- 帧号是22位,但二进制表示时要在高位补0。直接拿整数移位容易忽略高位补零,导致密钥流错位。
- 空转100拍时,仍然要执行多数表决逻辑。有些人为了省事让三个寄存器全部同步走100拍,结果初始化状态和标准不符。
- 上行/下行密钥流的生成顺序。这个上文提过,最容易错。
- COMP128的Kc提取。不同版本的COMP128(1、2、3)内部布局不同,提取Kc的比特位置也不一样,不要拿COMP128的逻辑去套COMP128-2。
6.4 测试向量是救命稻草
做协议实现时,建议找一组权威测试向量来验证。GSM标准文档(如ETSI TS 100 929)和应用笔记里会提供A5/1的输入输出对。拿到一个已知的Kc、帧号、预期密钥流,然后对着跑,保证自己的实现不是“自洽但错误”的。
我习惯的做法是写一个自动化测试脚本,输入Kc和帧号,输出228比特密钥流,然后和标准向量逐位比对。如果中间某一位错,就从初始化阶段开始打印寄存器状态,和标准文档中的中间状态对比,快速定位问题。
6.5 从GSM到LTE:这套老算法还有没有用
今天看A3/A5/A8,很多人觉得是博物馆里的展品。但我的观点是:理解这套老算法依然有价值,尤其在工业物联网、车联网等场景里,很多存量模块仍在跑GSM。而且从安全架构设计的角度看,A3/A5/A8的“认证-密钥生成-数据加密”三层解耦思路,一直到5G都还在沿用。5G里的5G-AKA流程本质上也还是这个套路,只是用上了更现代化的密码学组件。
我在实际项目里的体会是:GSM这一代算法的设计思路,核心价值不在复杂度和强度,而在于“分工明确、工程可实现”。在当年芯片算力极其有限的前提下,用LFSR+查表的方式实现了基本安全,是一个很务实的选择。今天看到A5/1被破解,不用觉得惊讶,重要的是理解它为什么会被时代淘汰,以及它如何影响了下一代系统的设计方向。
7. 最后再分享一点个人经验
如果你是为了做逆向分析或者协议研究去读这些算法的资料,我的建议是从A5/1入手,它的结构最直观,又足够有挑战性。先写一个纯Python版本,跑通A5/1加密一个帧,再去研究COMP128和A3/A8的配合流程。等你把A5/1的每个比特都摸透了,再回头看A5/2的攻击论文,会顺畅很多。
至于A5/3,核心是基于KASUMI分组密码的f8模式,设计哲学和A5/1完全不同。直白说,A5/3是“用现代分组密码思维替代了老旧LFSR思维”的产物。想要深刻理解这套演进,最扎实的路径还是先把A5/1吃透,再迁移到A5/3。踩过几次坑之后,你会发现这些算法背后的工程取舍和设计权衡,比算法本身更有意思。
本文还有配套的精品资源,点击获取