4. 安全元件通信协议:ISO 7816、ISO 14443、SPI/I2C 与 APDU 指令详解
通信协议,说白了就是安全元件(SE)跟外界对话的“语言”。你选错了协议,芯片再强也白搭。我这些年调试过的设备里,至少有三成因协议适配问题导致项目延期。今天咱们就把这几种主流协议掰开揉碎讲清楚。
4.1 接触式通信:ISO 7816
ISO 7816 是接触式智能卡的祖宗协议。你手里的银行卡、SIM 卡,用的就是它。它定义了物理接口、电气特性和传输协议。
4.1.1 物理接口
标准接触式接口有 8 个触点(C1~C8),但实际常用的就几个:
- C1(VCC):供电,通常 5V、3V 或 1.8V
- C2(RST):复位信号
- C3(CLK):时钟信号,频率通常 1~5 MHz
- C5(GND):地
- C7(I/O):半双工数据线
4.1.2 传输协议:T=0 与 T=1
ISO 7816-3 定义了两种传输协议:
| 特性 | T=0(字符传输) | T=1(块传输) |
|---|---|---|
| 数据单位 | 单字节 | 数据块(含 CRC) |
| 错误检测 | 奇偶校验 | CRC + 重传机制 |
| 典型应用 | SIM 卡、老式银行卡 | Java Card、高端 SE |
| 传输效率 | 较低 | 较高 |
我个人习惯优先选 T=1。为什么?T=0 的奇偶校验在强干扰环境下容易误判。之前有个项目在工业现场用 T=0,数据错得一塌糊涂,换成 T=1 后问题全解决了。
4.2 非接触式通信:ISO 14443
ISO 14443 定义了 13.56 MHz 的非接触式通信标准。你刷公交卡、用手机支付,背后都是它在工作。
4.2.1 四种类型
- Type A:基于 Miller 编码和 ASK 调制。典型代表:MIFARE Classic。
- Type B:基于 NRZ 编码和 BPSK 调制。典型代表:二代身份证。
- Type C:索尼的 FeliCa 方案,日本市场主流。
- Type D:ISO 15693 衍生,主要用于标签类应用。
4.2.2 防冲突机制
非接触式通信有个麻烦:多张卡同时靠近怎么办?ISO 14443 用“位级防冲突”解决。读卡器发一个请求,所有卡片回复自己的 UID。如果发生冲突(同一比特位有 0 和 1),读卡器就能识别出多张卡的存在,然后逐个选择。
嗯,这里要注意:防冲突算法在 Type A 和 Type B 里实现方式不同。Type A 用“比特掩码”法,Type B 用“时隙”法。我建议你在做多卡共存场景时,优先用 Type B 的时隙法,它在高并发下更稳定。
4.3 直连模式:SPI 与 I2C
物联网设备里,安全元件经常直接焊在 PCB 上,不需要插拔。这时候 SPI 和 I2C 就派上用场了。
4.3.1 SPI 模式
- 全双工:MOSI 和 MISO 同时传数据
- 速率高:通常 10~50 MHz,适合大数据量传输
- 引脚多:至少 4 根线(SCLK、MOSI、MISO、CS)
- 典型场景:安全固件升级、批量证书写入
4.3.2 I2C 模式
- 半双工:SDA 线双向传输
- 速率低:标准 100 kHz,快速 400 kHz
- 引脚少:只需 2 根线(SCL、SDA)
- 典型场景:传感器数据签名、密钥协商
| 对比项 | SPI | I2C |
|---|---|---|
| 引脚数 | 4+ | 2 |
| 速率 | 高(10~50 MHz) | 低(100~400 kHz) |
| 多设备支持 | 片选线控制 | 地址寻址 |
| 功耗 | 较高 | 较低 |
4.4 APDU 指令格式详解
APDU(Application Protocol Data Unit)是安全元件通信的“通用语言”。不管底层是 7816、14443 还是 SPI,上层指令都是 APDU。
4.4.1 命令 APDU(C-APDU)
主机发给 SE 的指令,结构如下:
| CLA | INS | P1 | P2 | Lc | Data | Le |
| 1B | 1B | 1B | 1B | 1B | Lc B | 1B |
- CLA:指令类别,比如 0x00 表示 ISO 标准指令
- INS:指令码,比如 0xA4 表示 SELECT FILE
- P1/P2:参数,用于指定操作细节
- Lc:Data 字段的长度(可为 0)
- Data:要发送的数据
- Le:期望返回的数据长度(可为 0)
4.4.2 响应 APDU(R-APDU)
SE 返回给主机的应答:
| Data | SW1 | SW2 |
| Le B | 1B | 1B |
- Data:返回的数据(长度由 Le 决定)
- SW1/SW2:状态字,表示执行结果
4.4.3 常见状态字
| SW1 | SW2 | 含义 |
|---|---|---|
| 0x90 | 0x00 | 操作成功 |
| 0x61 | 0xXX | 还有 XX 字节数据可读 |
| 0x6A | 0x82 | 文件未找到 |
| 0x69 | 0x85 | 安全条件不满足 |
| 0x6E | 0x00 | CLA 不支持 |
4.4.4 一个完整的 APDU 交互示例
假设我们要选择安全元件里的“密钥文件”:
// 命令:SELECT FILE
// CLA=0x00, INS=0xA4, P1=0x00, P2=0x0C
// Lc=0x02, Data=0x3F 0x00 (MF 主文件)
// Le=0x00
发送: 00 A4 00 0C 02 3F 00 00
// 响应:成功
接收: 90 00
你想想看,整个交互就这么简单。但实际项目里,APDU 链式调用、大数据分片传输才是真正的难点。我建议你一开始就封装好 APDU 收发函数,别在业务代码里拼字节流,否则后期维护会想哭。
4.5 本章知识体系总览
下面这张图帮你理清四种通信协议的关系和适用场景:
这张图把四种协议的关系讲得很清楚。底层传输方式不同,但上层都用 APDU 统一交互。你选协议时,先看物理形态(接触/非接触/直连),再看速率和功耗需求,最后用 APDU 封装业务逻辑。这套思路我用了十年,没出过大问题。