安全通道协议详解
SCP(Secure Channel Protocol,安全通道协议)系列是智能卡(尤其是SIM卡、UICC)与外界(如手机、OTA服务器)建立安全通信的核心机制。这些协议解决了同一个核心问题:如何在不可信的信道上,安全地传输指令和数据。
根据应用场景和协议栈的不同,SCP主要分为两大类:一类用于本地安全通道(SCP02、SCP03),另一类用于远程文件管理(SCP80、SCP81)。
下面的表格对比了这四种协议的核心特性:
| 协议 | 核心用途 | 安全机制 | 典型应用场景 |
|---|---|---|---|
| SCP02 | 本地安全通道 (GlobalPlatform) | 3DES对称密钥、MAC校验、可选加密 | 发卡后初始化、敏感文件写入(如网络锁定、IMSI更新) |
| SCP03 | 本地安全通道 (GlobalPlatform) | AES对称密钥(更安全)、多样化派生密钥 | 高安全等级的个人化操作(如eSIM配置文件下载、支付应用安装) |
| SCP80 | 远程文件管理 (OTA) | SMS-CB、USSD为载体,分段传输,安全包结构 | 通过短信发送小数据包(如运营商服务菜单更新、开机欢迎语) |
| SCP81 | 远程文件管理 (OTA) | CAT_TP (BIP) 或 HTTPS为载体,TCP/IP通道 | 通过BIP通道进行大数据量交互(如手机营业厅应用下载、大文件更新) |
SCP02 与 SCP03:本地安全通道
SCP02和SCP03主要用于卡和终端(或读卡器)之间的本地会话安全。它们通过“安全通道”的建立,确保后续发送的APDU指令(如写入关键文件)不被窃听或篡改。
SCP02
这是GlobalPlatform(全球平台组织)定义的第一代安全通道协议,基于3DES算法。
- 主要场景:卡片生命周期管理,尤其是在发卡后对卡片进行初始化和个人化操作。
- 核心指令:
INITIALIZE UPDATE和EXTERNAL AUTHENTICATE。
APDU指令示例:建立SCP02安全通道的过程
第一步:初始化更新 (INITIALIZE UPDATE)
终端发送此指令,向卡片发起建立安全通道的请求,并携带随机数等挑战信息。
# CLA INS P1 P2 Lc 数据域 |
第二步:外部认证 (EXTERNAL AUTHENTICATE)
卡片返回INITIALIZE UPDATE响应(包含卡片随机数、卡片密钥衍生数据等)。终端根据这些信息计算会话密钥,并发送EXTERNAL AUTHENTICATE进行认证。
# CLA INS P1 P2 Lc 数据域 (包含加密后的主机认证数据) |
成功执行后,终端和卡片之间就建立了一个安全通道。后续的PUT DATA、STORE DATA等指令可以带上安全报文(即加密和MAC校验值)通过该通道发送。
SCP03
SCP03是SCP02的升级版,基于更先进的AES算法,并支持多种密钥派生模式,安全性更高。
- 主要场景:eSIM(嵌入式SIM卡)配置文件的下载、金融级支付应用的安装等高安全等级场景。
- 核心指令:
INITIALIZE UPDATE和EXTERNAL AUTHENTICATE(指令代码与SCP02相同,但数据结构不同)。
与SCP02相比,SCP03的INITIALIZE UPDATE指令在数据域中包含了更丰富的参数,用于协商使用AES算法。后续的安全报文也使用AES-CMAC和AES加密,而非3DES。
SCP80 与 SCP81:远程文件管理
SCP80和SCP81主要用于运营商对已发行的SIM卡进行远程管理(OTA,Over-The-Air)。终端(手机)在这里扮演一个透明的传输通道角色。
SCP80
SCP80利用短信或USSD等无连接通道传输数据。由于短信有长度限制(通常140字节),数据包需要分段、重组和确认。
- 主要场景:发送小数据量、非实时的管理指令,如更新运营商服务菜单(STK菜单)、修改开机问候语、更新禁用网络列表等。
- 载体:SMS-CB(小区广播)、SMS-PP(点对点短信)、USSD。
- 核心机制:将应用层数据封装成短消息传输协议数据单元,然后通过
ENVELOPE (SMS-PP DOWNLOAD)或ENVELOPE (USSD)指令送入SIM卡。
APDU指令示例:手机将接收到的OTA短信转发给SIM卡
手机收到一条特殊格式的OTA短信(例如用于更新SIM服务菜单),手机会将其解析为APDU指令发给SIM卡处理。
# CLA INS P1 P2 Lc 数据域 (数据域包含封装好的SMS-PP TPDU) |
这条指令的CLA常为80或00,INS为00(ENVELOPE)。数据域里封装的是一个TPDU(传输协议数据单元),里面才包含着真正的SCP80安全包。
SCP81
SCP81利用CAT_TP (Card Application Toolkit Transport Protocol) 或BIP (Bearer Independent Protocol) 等基于IP的通道传输数据。
- 主要场景:需要大数据量、实时性交互的场景。比如通过手机自带的“运营商服务”应用(如中国移动的“我的SIM”应用)去下载一个几MB大小的文件,或者进行在线话费查询。
- 载体:BIP (TCP/IP)、CAT_TP、HTTPS。
- 核心机制:SIM卡扮演网络客户端角色,终端为其提供一个数据管道。
APDU指令示例:建立BIP通道和发送数据
SCP81的交互过程远比SCP80复杂,涉及终端和SIM卡之间一系列复杂的APDU指令交互。
第一步:打开BIP通道
SIM卡主动通过FETCH指令要求终端打开一个数据通道(如GPRS或Wi-Fi)。
# 终端 -> 卡: 告知卡有数据可获取 |
第二步:数据交换
通道建立后,SIM卡再次通过FETCH指令发送HTTP请求报文,终端接收后将报文发送到网络服务器,并将服务器的响应通过TERMINAL RESPONSE指令回传给SIM卡。
# 卡 -> 终端: 发送一个FETCH请求,获取待发送的数据 |
在整个SCP81过程中,APDU指令主要起到一个“指挥”和“搬运工”的作用,实际的数据内容(如HTTP报文)被封装在APDU的数据域中。
总结
- SCP02/SCP03 关注的是本地接口的安全,解决的是“本地连接如何信任”的问题。区别在于算法和安全性等级。
- SCP80/SCP81 关注的是远程传输的安全,解决的是“通过手机网络如何管理”的问题。区别在于传输载体和数据量的大小。
加密过程详解
SCP03的“加密”和“MAC计算”是它保证数据机密性和完整性的核心技术。简单来说,加密使用的是AES算法,确保数据不被窃听;而MAC计算使用的是AES-CMAC算法,确保数据不被篡改。
在SCP03安全通道建立后,通信双方(如手机和SIM卡)会协商出三个会话密钥,它们分别承担不同的安全职责:
| 密钥名称 | 全称及用途 | 算法 |
|---|---|---|
| S-ENC | 会话加密密钥:用于对发送的命令数据进行加密,保证机密性。 | AES(通常为128位或256位) |
| S-MAC | 会话命令MAC密钥:用于为发送的命令计算MAC,保证命令的完整性,并验证其来源。 | AES-CMAC |
| S-RMAC | 会话响应MAC密钥:用于为收到的响应计算MAC,保证响应的完整性,并验证其来源。 | AES-CMAC |
在安全通信阶段,发送方(通常是终端)会使用S-ENC和S-MAC对APDU指令进行处理,接收方(通常是卡片)则使用对应的密钥进行解密和校验。其核心流程如下:
flowchart TD |
加密过程详解
当需要保护数据内容的机密性时(例如写入密钥或敏感个人信息),就会对APDU指令的数据域进行加密。
- 算法:使用AES算法,通常采用CBC模式。需要初始向量(IV),在SCP03中,IV通常被固定为
16字节的0x00。 - 填充:由于AES是分组密码,要求输入数据长度是16字节的整数倍。因此,加密前需要对明文数据使用ISO/IEC 9797-1 Padding Method 2进行填充,即在数据后依次添加
0x80和若干个0x00,直至长度满足要求。 - 加密对象:仅加密APDU指令的数据域(Data Field)。指令的头部(CLA, INS, P1, P2)是不加密的,因为它们需要被卡片路由和处理。
- 指令标识:启用加密后,APDU指令的
CLA字节通常会从0x00或0x80变为0x84,用于告知卡片“本条指令的数据部分是加密的”。
MAC计算详解
MAC用于确保指令的完整性和真实性,防止指令在传输过程中被篡改。
- 算法:使用AES-CMAC算法。这是一种基于AES的、更安全的MAC算法。
- 计算范围:需要计算整个APDU指令中除MAC自身以外的所有部分,包括CLA, INS, P1, P2, Lc(长度)和加密后的Data(数据域)。
- 链式依赖(关键!):为了防止重放攻击并确保指令的顺序性,SCP03引入了MAC Chaining Value机制。简单来说,当前指令的MAC计算依赖于上一条指令的部分计算结果。因此,多条指令必须按顺序发送和处理,不能乱序。
- 截断:AES-CMAC算法完整计算出的结果是16字节。但在APDU指令中,为了节省空间,只会取前8个字节附加在指令末尾作为最终的MAC值。
一个完整的APDU指令示例
假设有一条明文指令 00 A4 00 00 02 3F00(选择MF文件)。启用SCP03的安全报文后,它会被封装成类似下面的样子:
# 格式: CLA INS P1 P2 Lc 数据域(加密后的数据) MAC(8字节) |
- CLA (
0x84):从0x00变为0x84,表示这是一个启用了安全报文(加密+MAC)的指令。 - Lc (
0x22):长度字段,它现在表示“加密后的数据域 + MAC”的总长度。 - 数据域 (34字节):原本的
3F00经过填充、加密后,变成了一个很长的密文。 - MAC (
C36703B133EE13A8):卡片的COS会使用S-MAC密钥,按照同样的规则重新计算MAC,并与指令携带的8字节MAC进行比对。只有比对成功,指令才会被执行。
关键操作注意事项
- 初始化是前提:所有上述加密和MAC计算,都必须在成功执行
INITIALIZE UPDATE和EXTERNAL AUTHENTICATE指令、建立安全通道并派生会话密钥之后才能进行。 - 脚本链接:在处理多条指令时,必须使用“脚本链接”机制,告诉卡片所有指令都属于同一个会话。这通常通过在指令前添加特定的TLV标签(如
AE80830101表示指令1)来实现。 - 响应也要验证:卡片返回的响应APDU同样会受到保护。终端需要使用 S-RMAC 密钥来验证响应中的MAC,确保响应没有被篡改。
加密和MAC计算细节
这个过程在安全通道建立之后进行,假设已经成功执行了INITIALIZE UPDATE和EXTERNAL AUTHENTICATE,派生出了三个会话密钥:S-ENC(加密密钥)、S-MAC(命令MAC密钥)和S-RMAC(响应MAC密钥)。
会话密钥(示例值)
为便于演示,假设以下128位AES密钥(十六进制):
| 密钥 | 值(16字节) |
|---|---|
| S-ENC | 404142434445464748494A4B4C4D4E4F |
| S-MAC | 505152535455565758595A5B5C5D5E5F |
| S-RMAC | 606162636465666768696A6B6C6D6E6F |
实际场景中,这些密钥是通过卡片和终端交换的随机数,结合主密钥派生的。
加密过程(AES-CBC)
加密仅应用于APDU指令的数据域(Data Field),目的是保证机密性。
步骤:
- 明文数据:待加密的原始数据(例如选择文件的AID或写入的个人化数据)。
- 填充(ISO/IEC 9797-1 Method 2):
- 在数据后添加一个字节
0x80。 - 然后添加足够的
0x00,使总长度为16字节的整数倍。 - 如果原始数据长度已经是16字节的倍数,则仍需添加16字节:
0x80后跟15个0x00。
- 在数据后添加一个字节
- IV:初始向量固定为16字节全
0x00。 - 加密:使用AES-128-CBC模式(SCP03通常支持AES-128,也可用AES-256,这里以AES-128为例)对填充后的数据进行加密。
示例
假设要发送一条选择MF(主文件)的APDU指令,原始指令为:00 A4 00 00 02 3F00
明文数据域(3F00)长度为2字节。
填充:
- 添加
0x80→3F00 80 - 补
0x00至16字节 →3F00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 - 最终16字节:
3F 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00
AES-CBC加密(IV=全0):
使用密钥404142434445464748494A4B4C4D4E4F加密后,得到16字节密文(以C1…C16表示)。假设计算结果为:3A 92 3F 8C 6F 9E 4C B9 7E 2A D3 8E 1B 5C 9F 4E
(这仅为示例,实际结果取决于密钥和算法实现)
MAC计算过程(AES-CMAC)
MAC用于保证指令的完整性和真实性,防止重放攻击,SCP03中采用链式MAC(MAC Chaining)。
步骤:
构建输入数据:需要计算MAC的数据包括:
- 修改后的
CLA(将原CLA的bit 2设为1,例如00→84) INS、P1、P2Lc(表示密文长度 + MAC长度,即最终指令数据域的总字节数)- 密文(即上述加密后的数据)
- 注意:MAC本身不参与计算。
- 修改后的
链值(Chaining Value):
- 对于第一条安全指令,链值为16字节
0x00。 - 对于后续指令,链值为上一条指令计算出的16字节MAC值(即完整的AES-CMAC结果,非截断)。
- 链值参与MAC计算,使得指令顺序不可调换。
- 对于第一条安全指令,链值为16字节
计算MAC:使用AES-CMAC算法,输入为(链值 || 上述输入数据),输出16字节MAC值。
截断:取前8字节作为最终附加在指令中的MAC。
示例(接上一条SELECT MF指令):
已得到密文(16字节),现在构建MAC输入。
修改CLA:
原CLA为00,启用安全报文后改为84(表示加密+MAC)。
计算Lc:
- 密文长度 = 16字节
- MAC长度 = 8字节
- 总数据域长度 = 16 + 8 = 24字节 =
0x18
构造MAC输入数据:
CLA INS P1 P2 Lc 密文 →84 A4 00 00 18 3A 92 3F 8C 6F 9E 4C B9 7E 2A D3 8E 1B 5C 9F 4E
计算链值:
因为是第一条安全指令,链值 = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00。
AES-CMAC计算:
输入 = 链值 || 上述数据,使用S-MAC密钥505152535455565758595A5B5C5D5E5F,得到16字节CMAC结果。假设结果为:7B D6 2F 1A 3E 9C 5B D8 0F 4A 3E 7C D1 8F 2B 6E
截取前8字节作为MAC:
7B D6 2F 1A 3E 9C 5B D8
构建最终安全APDU
将加密后的密文和MAC拼接,形成数据域,并组装APDU:
84 A4 00 00 18 密文(16字节) MAC(8字节) |
即:84 A4 00 00 18 3A 92 3F 8C 6F 9E 4C B9 7E 2A D3 8E 1B 5C 9F 4E 7B D6 2F 1A 3E 9C 5B D8
卡片收到后,会先用S-MAC验证MAC,成功后再用S-ENC解密数据域(去除MAC部分),得到明文。
多条指令时的链值更新
假设要发送第二条安全指令,链值应为上一条指令的完整16字节CMAC结果(即7B D6 2F 1A 3E 9C 5B D8 0F 4A 3E 7C D1 8F 2B 6E)。计算第二条指令的MAC时,输入数据最前面先拼接这个链值,然后再接CLA…密文。
这种链式机制强制了指令的顺序性,有效防止重放攻击。
响应报文的MAC验证
卡片返回的响应(Status Word前)也可能包含一个8字节的MAC,终端需要用S-RMAC密钥按相同规则计算并验证。计算方法类似,但输入数据为响应报文的状态码之前的部分。
注意事项
- CLA字节规则:当使用加密+MAC时,
CLA通常设为0x84(即原CLA的bit 2置1)。若仅使用MAC而不加密,则设为0x04(数据域为明文+MAC)。 - 长度字段:
Lc必须准确反映加密数据+MAC的总长度,否则卡片会报长度错误。 - 密钥长度:SCP03支持AES-128、192、256,实际使用取决于卡片和终端的协商结果,一般在
INITIALIZE UPDATE时确定。 - IV的变体:部分实现可能使用全0之外的IV,但SCP03标准明确CBC模式IV为全0。
INITIALIZE UPDATE 和 EXTERNAL AUTHENTICATE
接下来详细解析 SCP03 安全通道建立的核心步骤:INITIALIZE UPDATE 和 EXTERNAL AUTHENTICATE。这两个指令完成会话密钥的派生和双向认证,为后续的安全报文传输奠定基础。
前提条件
- 卡片已经预置了与终端共享的静态主密钥(通常是AES-128/192/256,如KENC、KMAC、KRMAC,但实际SCP03使用一对静态主密钥,分别用于加密和MAC,并通过KDF派生出会话密钥)。
- 终端知道这些主密钥,并拥有卡片的识别信息(如卡片序列号ICCID、ISD AID等)。
- 支持SCP03的卡片和终端都实现了GlobalPlatform规范中定义的SCP03协议。
INITIALIZE UPDATE(初始化更新)
这是安全通道建立的第一步,终端向卡片发起挑战,卡片返回随机数和派生数据。
指令格式
CLA INS P1 P2 Lc 数据域 |
CLA:84表示启用安全报文(安全通道相关指令)。INS:70是INITIALIZE UPDATE的指令码。P1,P2: 通常为00 00。Lc: 数据域长度,取决于数据域中的内容。- 数据域:包含终端的挑战值(
Host Challenge)和可选参数。
数据域结构(TLV格式):
| 标签 | 长度 | 值 |
|---|---|---|
80 |
8 | Host Challenge(终端随机数,8字节) |
81 |
1 | Key Diversification Data Length(可选) |
82 |
可变 | Key Diversification Data(可选,用于密钥派生) |
83 |
2 | Key Version Number(可选,密钥版本号) |
实际规范要求至少包含 80 标签的终端挑战值。
示例指令(假设终端产生8字节挑战 1122334455667788,无其他可选数据):84 70 00 00 0C 80 08 11 22 33 44 55 66 77 88
解释:84 70 00 00 头部,Lc=0C(12字节),数据域为 80 08 后跟8字节挑战值。
卡片响应
卡片处理 INITIALIZE UPDATE 后,返回响应数据(TLV格式),通常包含:
| 标签 | 长度 | 值 |
|---|---|---|
80 |
8 | Card Challenge(卡片随机数,8字节) |
81 |
可变 | Card Cryptogram(卡片密码,16字节或更多) |
82 |
可变 | Key Diversification Data(密钥派生数据,可选) |
83 |
2 | Key Version Number(可选) |
84 |
1 | Secure Channel Protocol Options(SCP选项,指示使用的算法、密钥长度等) |
其中 Card Cryptogram 是使用主密钥对某些数据计算得到的,用于终端验证卡片身份。
响应示例(假设卡片返回8字节挑战 AABBCCDDEEFF0011,Card Cryptogram 16字节,SCP Options = 80 表示AES-128):80 08 AA BB CC DD EE FF 00 11
81 10 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10
84 01 80
(实际响应中每个TLV连续排列,这里为了清晰分行)
会话密钥派生(Key Derivation)
终端收到卡片的响应后,结合自己的主密钥和交换的随机数,派生出三个会话密钥:S-ENC(加密密钥)、S-MAC(命令MAC密钥)、S-RMAC(响应MAC密钥)。
SCP03的密钥派生使用 KDF (Key Derivation Function),具体为:KDF(C, L),其中 C 是派生输入(包含卡挑战、主机挑战等),L 是期望密钥长度。通常基于 AES-CMAC 或 AES-CBC-MAC 实现。
派生步骤(简化)
构建 派生字符串:
D = 00 00 00 01 || 卡挑战(8字节) || 主机挑战(8字节) || 00 00 00 02 || 卡挑战 || 主机挑战 || ...(根据需要的密钥数量重复)
实际GlobalPlatform规范有明确的结构,包含计数器、上下文、算法标识等。
使用静态主密钥(如 KMAC)对派生字符串计算 AES-CMAC,得到的结果作为会话密钥。
重复该过程(改变计数器)得到不同用途的密钥。
示例(假设简化派生)
假设主密钥为 404142434445464748494A4B4C4D4E4F,卡挑战 CARD_CH,主机挑战 HOST_CH。派生S-ENC、S-MAC、S-RMAC的过程略复杂,但最终终端和卡片会通过相同算法得到完全一致的三个会话密钥。
EXTERNAL AUTHENTICATE(外部认证)
终端利用派生出的会话密钥构造认证数据,发送给卡片完成相互认证。
指令格式
CLA INS P1 P2 Lc 数据域 |
CLA:84。INS:82是EXTERNAL AUTHENTICATE。P1,P2:00 00。- 数据域:包含终端认证数据(TLV格式),可能还包含安全通道选项。
数据域结构(TLV):
| 标签 | 长度 | 值 |
|---|---|---|
80 |
16 | Host Cryptogram(终端密码,16字节) |
81 |
可变 | Secure Channel Protocol Options(可选) |
Host Cryptogram 的计算:使用 S-MAC 密钥对某些数据(如卡挑战、主机挑战、密钥派生数据等)计算 AES-CMAC 得到16字节结果,取前16字节作为Host Cryptogram。
示例指令(假设Host Cryptogram为 1234567890ABCDEF1234567890ABCDEF):84 82 00 00 12 80 10 12 34 56 78 90 AB CD EF 12 34 56 78 90 AB CD EF
卡片响应
卡片收到 EXTERNAL AUTHENTICATE 后,使用自身的会话密钥验证Host Cryptogram。如果验证通过,卡片返回一个 Card Authentication Cryptogram(卡认证密码),用于终端验证卡片(可选)。如果验证失败,卡片返回错误状态码。
响应示例(假设卡片返回16字节卡认证密码):80 10 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF
这个卡认证密码是卡片使用 S-RMAC 对某些数据计算得到的,终端可以用S-RMAC验证,完成双向认证。
安全通道建立完成
执行完 EXTERNAL AUTHENTICATE 并验证响应后,安全通道建立。此后,终端和卡片可以使用派生出的会话密钥对后续APDU指令进行加密和MAC保护(如前面所述)。
SCP03 与 SCP02 的主要区别
| 项目 | SCP02 | SCP03 |
|---|---|---|
| 算法 | 3DES | AES |
| 密钥长度 | 112/168位 | 128/192/256位 |
| 会话密钥派生 | 基于3DES的特定KDF | 基于AES-CMAC的KDF,支持更多衍生数据 |
| 指令数据域结构 | 非TLV,固定顺序 | TLV结构,扩展性强 |
| 链式MAC | 基于3DES CBC-MAC | 基于AES-CMAC,链值机制更安全 |
| 会话密钥数量 | 3个(加密、MAC、RMAC) | 3个(S-ENC、S-MAC、S-RMAC) |
实际注意事项
- 版本协商:
INITIALIZE UPDATE的数据域中可能包含密钥版本号、SCP选项,用于协商算法强度。 - 卡片状态:安全通道建立后,卡片内部状态机进入安全模式,后续指令必须携带正确的安全报文。
- 多会话支持:卡片可能同时支持多个安全通道,通过上下文区分。
- 错误处理:如果
INITIALIZE UPDATE或EXTERNAL AUTHENTICATE失败,卡片会返回特定状态码(如6982安全状态不满足,6A88引用数据未找到等)。