第三章 APDU通信协议:智能卡与世界的对话

APDU,全称是Application Protocol Data Unit。说白了,就是智能卡和外界通信时用的“语言”。我刚开始接触JCOP开发时,觉得这东西不就是发几个字节嘛,有什么难的?结果第一次调通通信就花了整整两天——因为一个字节的顺序搞反了。

嗯,咱们今天就把这块彻底讲透。

3.1 APDU命令格式

APDU命令分两种:短APDU和扩展APDU。咱们平时用的最多的是短APDU,结构如下:

CLA INS P1 P2 [Lc] [Data] [Le]

每个字段的含义:

字段 长度 说明
CLA 1字节 指令类别,00表示ISO标准,80表示私有
INS 1字节 指令码,比如A4是SELECT,B0是READ BINARY
P1/P2 各1字节 参数,具体含义看指令定义
Lc 0或1字节 命令数据的长度(如果后面有数据)
Data Lc字节 实际发送的数据
Le 0或1字节 期望响应的最大长度

关键点:CLA和INS的组合决定了卡片要做什么。我见过不少新手把INS和P1搞混,结果卡片一直返回6A86(错误的INS)。

举个例子,SELECT命令(选择文件):

00 A4 04 00 02 3F 00

这里CLA=00,INS=A4,P1=04(按文件名选择),P2=00,Lc=02,Data=3F00(MF的标识符),Le省略。

3.2 APDU响应格式

卡片处理完命令后,会返回响应。格式很简单:

[Data] SW1 SW2

SW1和SW2是状态字,共2字节。Data是可选的,取决于命令。

常见的状态字:

SW1 SW2 含义
90 00 成功!我最喜欢看到这个
6A 82 文件未找到
6A 86 P1/P2参数错误
69 85 安全条件不满足
67 00 Lc长度错误

避坑指南:我曾经在项目中遇到一个诡异的问题——卡片偶尔返回6A 88(引用数据无效)。查了两天,最后发现是上位机发送数据时,Lc字段写错了。Lc必须等于后面Data的实际长度,多一个字节少一个字节都不行。

3.3 T=0与T=1协议

这两个是传输协议,决定了数据怎么在物理层上传输。你想想看,APDU是应用层的“语言”,而T=0和T=1是“运输方式”。

T=0协议:面向字符的传输。每次只传一个字节,适合低速场景。它的特点是:

  • 卡片收到命令后,先返回一个过程字节(0x60表示继续,0x61+Le表示有数据要返回)
  • 如果命令有Data,卡片会通过过程字节告诉终端“我准备好了,你发数据吧”
  • 响应时,先返回SW1,再返回SW2

T=1协议:面向块的传输。把数据打包成块(block)发送,效率更高。它的特点是:

  • 每个块有头信息(NAD、PCB、LEN)和CRC校验
  • 支持链式传输(数据太长时分多次发送)
  • 有重传机制,可靠性更高

我的经验:JCOP卡片通常同时支持T=0和T=1。我个人习惯用T=1,因为调试时能看到完整的块结构,出问题容易定位。但有些老旧读卡器只支持T=0,这时候就得兼容。

3.4 链路层与传输层

链路层负责物理连接的管理。在ISO 7816标准中,链路层主要处理:

  • 复位应答(ATR):卡片上电后发送的第一串数据,告诉终端“我是谁,我支持什么”
  • 协议参数选择(PPS):终端和卡片协商用T=0还是T=1
  • 去激活:通信结束后的断电流程

传输层则是在链路层之上,负责APDU的收发。说白了,就是把APDU命令拆成T=0或T=1能处理的格式,发出去,再把响应拼回来。

这里有个容易忽略的点:ATR中的TA1字节决定了时钟频率转换因子(F)和比特率调整因子(D)。我见过有人用高速读卡器去读一张老卡片,结果通信失败——因为卡片不支持那么高的速率。

3.5 核心知识体系

下面这张图是我自己整理的APDU通信协议知识结构,你看一眼就能明白整体脉络:

APDU通信协议知识体系 APDU协议 命令格式 响应格式 T=0协议(面向字符) T=1协议(面向块) 链路层:ATR、PPS、去激活 物理层:ISO 7816-3电气特性 关键:APDU是应用层协议,T=0/T=1是传输层协议,链路层负责物理连接管理 三者层层封装,缺一不可

3.6 实战中的注意事项

最后分享几个我在项目中踩过的坑:

  1. Le字段的陷阱:如果Le=0x00,表示期望最多256字节响应。但有些卡片会把0x00理解为0字节,导致返回空数据。我建议明确写Le值,别偷懒。
  2. 过程字节的处理:T=0协议下,卡片返回0x60表示“我还在忙”。这时候终端必须继续发送0x60直到卡片返回其他值。我见过有人只发一次0x60就放弃了,结果通信超时。
  3. ATR的解析:ATR中的历史字节(Historical Bytes)不是必须的,但很多卡片会用它来传递一些厂商信息。别假设所有卡片的ATR格式都一样。
  4. CRC校验:T=1协议中每个块都有CRC。如果CRC错误,卡片会要求重传。我曾经因为读卡器驱动没实现CRC校验,导致通信成功率只有70%。

小技巧:调试APDU通信时,我习惯用抓包工具(比如PC/SC的日志)把原始字节流记录下来。这样出问题时,可以逐字节分析,定位问题非常快。

好了,APDU通信协议这块就讲到这里。记住一句话:APDU是智能卡的“语言”,T=0和T=1是“运输方式”,链路层是“道路”。三者配合好了,卡片才能正常工作。


公众号:蓝海资料掘金营,微信deep3321