移动通信网的鉴权认证技术

先给个总体演进图。

VS

一、基本概念

移动通信网通常由三个部分组成,即核心网 (CN,core network)、无线接入网(RAN,radio access network)和用户设备(UE,user equipment)。 其中移动用户设备属于用户个人,由用户直接控制,接入网与核心网属于运营商,由运营商直接控制。如果用户希望使用运营商服务和网络资源,需要用户和运营商共同协商,这就涉及鉴权认证,判明和确认通信双方真实身份。

移动通信网的鉴权认证过程采用的是古老的“Challenge - Response”(挑战 - 响应)的机制,即认证方向被认证方发送一个“挑战”(一般是一个随机数),被认证方基于双方共有密钥,以及挑战中所包含的信息计算一个“响应”。显然,只有拥有密钥的参与方才能正确计算出这个响应。

一般情况下,认证可基于被认证方拥有一个独特的、不可复制的构件;或者双方都知道的一个秘密;又或者被认证方的某种唯一特征。
除第一代模拟通信外,从2G开始的移动通信网络的认证综合了前两种方式:一个共同的秘密(密钥)和被认证方一个独特的构件(SIM/USIM卡)。

移动通信网的鉴权认证是移动网络与终端用户之间相互识别的过程,核心是解决两个问题:

  1. 你是谁?
    基于国际移动用户识别号 IMSI(International Mobile Subscriber Identification)。
    IMSI 定义为 15 位的十进制数,其结构为:MCC + MNC + MSIN。
    全球运营商统一编码,是唯一且固定的身份标识,SIM/USIM 卡中存储了该数据。

  2. 你是不是你?
    基于永久性的根密钥 Ki,长度是 16 个字节,也就是 128 比特位。
    认证就是基于 Ki 共同秘密,配合一些其他的参数,基于一定的认证算法和协议过程而展开。
    Ki 仅在运营商的 AUC(Authentication Center)和用户的 SIM/USIM 卡中存储,基于根密钥的计算都在内部进行,绝对不允许对外暴露。
    后续需要使用的其它密钥(例如通信密钥 Kc),都是基于 Ki 通过不可逆的算法衍生出来的。

GSM

AUC 和 SIM/USIM 是移动通信网安全的基石之一。AUC在运营商网络之内,在物理上、管理机制上、安全防护手段上都有严格的要求,卡则散落在用户手里,是不可控的环境。通常卡都采用抵制篡改(tamper-resist)的硬件设计,即要求不能从卡内读出卡内的信息,从而防止信息的泄露。

二、GSM 的 鉴权流程

1. 三元组认证向量(RAND、XRES、Kc)

GSM 系统的鉴权流程在 GSM09.02 MAP 中定义,核心是三元组认证向量(RAND、XRES、Kc)。

  • RAND:移动网络AUC提供的随机数
  • XRES/SRES:AUC侧计算的期望响应值(eXperted RESponse),卡侧计算的鉴权响应值(Signed RESponse),检测 XRES == SRES
  • Kc:通信使用的一次性会话密钥,用于 A5 算法的加密输入

GSM

在这个6步的过程里面同时实现了认证和会话密钥协商,称为AKA(Authentication and Key Agreement,会话与密钥协商)协议。

2. COMP128-1 算法和克隆卡问题

AKA 协议定义了 A3 和 A8 算法,其中 A3 算法以 Ki 和 RAND 作为输入参数,负责生成 SRES(32bits),A8 算法同样以 Ki 和 RAND 作为输入参数,负责生成后续用于通信加密的会话密钥 Kc(64bits)。由于这两个算法的输入参数完全相同,绝大多数运营商都直接采用 COMP128-1算法。

COMP128-1 算法于1987年设计,1991年投入使用,其设计较为简单,其实现仅需20行代码,在最初设计与使用时,所有参与方签订协议对方法进行保密。

COMP128

R 为轮函数,P 为置换,F 为置换与抽取。由于R、P、F均为高强度非线性运算,整体呈现哈希的雪崩特性。

1998年,COMP128-1 算法被泄露,随即在1999年即被破解。究其原因,由于COMP128-1 算法中输入的信息(128bits)大于输出的信息(96bits,即SRES+Kc),因此必然会出现不同的输入产生相同的输出,也就是“碰撞”,而且由于字节压缩得很厉害,很容易找到“碰撞”。

2000年,出现了对应的SIM卡破解软件,攻击者输入大量连续的数据就能轻易获得碰撞,以此来推算出密钥Ki。一旦计算出Ki,SIM卡就可被复制。因此,对SIM卡的破解并不是从智能卡中读取了机密信息,而是利用算法的脆弱性实施了计算破解。

3. 单向鉴权和伪基站问题

GSM 认证机制最大的缺陷是“单向认证”,就是说只有网络认证用户的真实性,而用户不认证网络。

2009年,OpenBTS软件发布,攻击者购置主机和笔记本电脑,再加上一个射频装置,通过中间人攻击方式构造“伪基站”,其基本流程是:

  • 伪基站设备发射高强度的非法信号,用户终端自动连接到信号强度最高的基站并发送注册请求,这便暴露了自己的 IMSI
  • 伪基站设备侦听设备,冒充目标终端向运营商真实网络侧发起注册请求
  • 伪基站设备把网络下发的 RAND 转给受害者移动终端,并把终端返回的 SRES 转给网络,这就完成了鉴权认证流程

理论上说,如果伪基站接入了运营商网络,可以解析信令数据并通过 A5 算法解密话音数据,从而实现主叫通话的窃听功能(此时无法做被叫,因为终端未在公众通信网络注册),但由于这些功能实现较为复杂,实际上典型的犯罪应用是短信欺诈,即伪装成任意号码(例如95588、95533、10086等银行或通信运营商的客服号码)下发垃圾短信,或者伪造短信验证码。

三、CDMA 的鉴权流程

CDMA 系统的鉴权流程在 IS-41 MAP 中被详细定义。
CDMA 系统中用于移动台鉴权的密码分为两级,第一级为移动台的密钥 A_Key,第二级为共享加密数据(SSD,shared secret data)。

  • 密钥 A_Key是高级密码,长度为 64 bit,由运营商分配,它和 IMSI 一同被写入移动终端永久性存储器中。
    同时,运营商核心网存储该用户的 IMSI 和对应的 A_Key。该密钥是永久性的,不在网络和空中信道上传播。
  • SSD 是低级密码,长为 128 bit(分为 SSD_A 为 64 bit 和 SSD_B 为 64 bit),它由A_Key 运算产生,存在于移动台、鉴权中心和拜访者位置寄存器。
    在鉴权过程中,核心网使用RAND 和 SSD_A 计算出期望的响应 AUTHx,倘若移动终端计算的 AUTHx(用 RAND 和 SSD_A计算所得)和核心网计算的 AUTHx 相同,则鉴权成功,攻击者因没有正确有效的 SSD 值,无法计算得到核心网所期望的 AUTHx 值导致鉴权 失败]。

四、3G(UTMS)的鉴权流程

2000年,ITU 制定 3G 空口传输标准制式的时候,针对2G智能卡及网络的破解攻击已经存在。因此,在 3G 网络认证标准制定时,采用了两项关键技术:一是建立“用户+网络”的双向认证机制,二是将智能卡升级为USIM卡(Universal Subscriber Identity Module,全球用户识别卡),并选用更加安全的认证算法。

CMCC是个特例!因为政府只给了 TD-SCDMA 牌照,巨大的市场压力下提出“不换号、不换卡”的业务策略,直到 4G 时代才将 SIM 卡换成 USIM 卡。

1. 五元组认证向量(RAND, XRES, CK, IK, AUTN)

3G 标准的鉴权流程与 GSM 基本相同,关键是用户认证向量发生变化。

1

  1. 在第三步中,网络侧发送(RAND,AUTN)。不仅有用于挑战的随机数 RAND,还增加了 AUTN(Authentication Token)参数,使得 USIM 可以鉴别网络的真伪,防止接入伪基站
    • GSM 中的长期密钥Ki,3G 标准改名为 K,GSM AKA 也改为 UMTS AKA
    • AUTN 通过终端与归属网络之间的共享密钥K,以及一些其他输入参数计算得出
  2. 在第四步中,如果 AUTN 验证通过,USIM 基于长期密钥 K 计算形成(XRES,CK,IK)。
    • XRES:挑战的响应值,第五步将此上报给网络侧,实现网络对用户的认证,
    • CK:机密性保护密钥,与GSM的 Kc 对应
    • IK:完整性保护密钥,3G 标准新增

2. MILENAGE 算法簇

3GPP 使用代号为$f1$ - $f5$ 的5个算法来产生认证向量,但允许运营商自行决定采用何种具体算法,因为这些算法应用于 USIM 和 AUC 之间,不涉及到运营商之间的互操作。
3GPP 推荐使用基于 AES 的 MILENAGE 算法簇,加密分组和密钥长度都是128比特,

N

  • SQN:48bit序列号,通过序列号确保每个认证向量不会被重放;
  • AK:48bit用于隐藏序列号的临时密钥,基于K和RAND生成;
  • MAC:64bit,用于构成AUTN的主要变量,由于包含了K的计算,可用于作为网络认证;
  • AMF:Authentication Management Field,共16bit,未标准化。在4G的时候,最高位被用于区分AMF所在的认证向量是4G的认证向量还是3G的认证向量,因为4G和3G可能会共用HSS/AuC。

N

  • $f1(SQN, AFM, K) \Rightarrow MAC$
  • $f2(K,RAND) \Rightarrow XRES$
  • $f3(K, RAND) \Rightarrow CK$
  • $f4(K, RAND) \Rightarrow IK$
  • $f5(K, RAND) \Rightarrow AK$
  • $AUTN = SQN \oplus AK || MAC || AMF$

理论上来说,在3G认证过程实施之后就不会再出现伪基站了,但也有一些例外情况,如为了方便2G存量用户的使用,3G网络在推荐使用USIM卡接入的基础上、同时也允许SIM卡直接认证后接入;因此,对于使用SIM卡接入网络的用户还是容易受到2G伪基站的攻击。
另外,3G认证协议标准化不久,就发现易受到重定向攻击 (redirection attack) ,2017年的黑帽大会上有针对4G网络攻击案例被披露.

五、4G 的鉴权流程

4G 基本沿用了3G认证的协议流程和认证算法,只在卡的兼容性和后续密钥的衍生方面有少量的修改,称为 EPS-AKA,主要改进包括:

  1. LTE 仅允许 USIM 接入,不允许 SIM 接入,意味着双向认证和信令的完整性保护是必选的。
    但在少量特殊的情况下,例如终端被叫因为不支持 VoLTE 而被切换到 2G,或者 4G 过载向 2G 进行切换时,可能仍然存在伪基站的问题,2017 年的黑帽大会上就曝出了一个“呼叫劫持”漏洞。
  2. 为了支持 WLAN 的接入方式,提供了扩展的 EAP-AKA 和 EAP-AKA’ 认证。
    EAP-AKA 是将 AKA 认证过程使用 EAP 协议进行封装,其核心参数仍然是AKA认证向量,参与认证的网元有UE、AC、AAA Server、HSS。
    1

六、5G 的鉴权流程

5G 继承了 AKA 作为网络接入的认证方式,重点考虑认证体系的扩展,主要改进包括:

  1. 增强了归属网络对认证的控制。
    5G-AKA 对认证向量进行一次单向变换,拜访地运营商仅能获取漫游用户经过变换之后的认证向量,并将漫游用户反馈的认证结果发送给归属地。
    6
  2. 统一的认证框架更好支持 WLAN 等非蜂窝通信网络。
    一方面,5G 无线网接入可以采用 EAP-AKA’ 认证方式,EAP-AKA’认证方式提升到了和 5G-AKA 并列的位置;另一方面,EAP-AKA’ 认证和 5G-AKA 认证在网络架构上使用了同样的网元,意味着5G的认证网元在标准上必须同时支持这两种认证方式。

七、 总结

通信网络的认证协议,基于“挑战-响应”的AKA协议是一条贯穿始终的线索。但从2G到5G,AKA也一直在演进以适应形势的变化。所谓形势,主要是新的威胁的出现,或一些预期的安全风险逐渐变成现实。毕竟,算力在不断强大,而网络越来越复杂。AKA的演进,在AKA的前缀上表现出来:在2G的时候,AKA就叫AKA;在3G的时候,应对伪基站风险,增加了双向认证,解决了用户对网络的信任问题,3G的AKA被称为UMTS AKA;在4G的时候,Authentication部分没有变化,但Key Agreement发生了变化,针对无线网络、核心网络,衍生出不同的密钥,解决了无线网和核心网的互信问题,4G的AKA被称为EPS AKA;5G的AKA增强了归属网络的控制,解决归属网络和拜访网络的互信问题,并被称为5G AKA。

相对来说,算法变动倒是相对小些,在2G被证明不安全的COMP128在3G之后就被可以以AES为核心的MILENAGE替代,目前这个部分仍然被认为是安全的。

在AKA这条主脉络之外,5G作为一个“野心勃勃”的网络,在认证上也体现出与以往几代不同之处,如EAP。在4G的时候可以作为WLAN接入的认证方式,但并非特别重要。在5G中,EAP还承载了为外部数据网络提供认证服务、为垂直行业应用提供认证服务的职能,充分体现了5G希望超越“人与手机”的单一形态,从设计上就契合物联网、工业互联网等形态的需求。


附录一:COMP128 算法实现

COMP128 - Details

  1. x[16-31] = RAND
  2. for 0<i<8
    x[0-15] = Ki
    call Compression (5 rounds)
    call FormBitsFromBytes
    if i<7 call Permute

Compress 16-byte result to 12-bytes, store in simoutput[] and return.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
void comp128v1(const uint8_t *ki, const uint8_t *rand, uint8_t *sres, uint8_t *kc)
{
int i;
uint8_t x[32], bits[128];

/* x[16-31] = RAND */
memcpy(&x[16], rand, 16);

/* Round 1-7 */
for (i=0; i<7; i++) {
/* x[0-15] = Ki */
memcpy(x, ki, 16);

/* Compression */
_comp128_compression(x);

/* FormBitFromBytes */
_comp128_bitsfrombytes(x, bits);

/* Permutation */
_comp128_permutation(x, bits);
}

/* Round 8 (final) */
/* x[0-15] = Ki */
memcpy(x, ki, 16);

/* Compression */
_comp128_compression(x);

/* Output stage */
for (i=0; i<8; i+=2)
sres[i>>1] = x[i]<<4 | x[i+1];

for (i=0; i<12; i+=2)
kc[i>>1] = (x[i + 18] << 6) |
(x[i + 19] << 2) |
(x[i + 20] >> 2);

kc[6] = (x[30]<<6) | (x[31]<<2);
kc[7] = 0;
}

static inline void _comp128_compression(uint8_t *x)
{
int n;
for (n=0; n<5; n++)
_comp128_compression_round(x, n, _comp128_table[n]);
}

static inline void _comp128_bitsfrombytes(uint8_t *x, uint8_t *bits)
{
int i;
memset(bits, 0x00, 128);
for (i=0; i<128; i++)
if (x[i>>2] & (1<<(3-(i&3))))
bits[i] = 1;
}

static inline void _comp128_permutation(uint8_t *x, uint8_t *bits)
{
int i;
memset(&x[16], 0x00, 16);
for (i=0; i<128; i++)
x[(i>>3)+16] |= bits[(i*17) & 127] << (7-(i&7));
}

参考文献

文档下载