智能卡APDU指令详解:从入门到实战
约 3500 字 | 智能卡开发基础 | 2026-07
什么是 APDU?
APDU(Application Protocol Data Unit,应用协议数据单元)是智能卡与读卡器之间通信的核心协议。无论是银行卡、SIM 卡、身份证还是门禁卡,所有智能卡应用层的通信都通过 APDU 指令完成。理解 APDU 是智能卡开发的第一道门槛。
ISO 7816-4 标准定义了 APDU 的格式和交换机制。一条完整的 APDU 交互由命令 APDU(C-APDU)和响应 APDU(R-APDU)组成。读卡器发送 C-APDU,卡片处理后返回 R-APDU。
C-APDU 命令结构
一条标准的命令 APDU 由必选头部(4字节)和可选体部(可变长)组成:
| 字段 | 长度 | 含义 | 说明 |
|---|---|---|---|
CLA | 1 byte | 指令类别 | 标识指令类型,如 0x00=ISO标准、0x80=GP规范、0xA0=应用私有 |
INS | 1 byte | 指令代码 | 具体操作,如 0xA4=SELECT、0xB0=READ BINARY、0xB2=READ RECORD |
P1 | 1 byte | 参数 1 | 指令参数,含义取决于 INS |
P2 | 1 byte | 参数 2 | 指令参数,含义取决于 INS |
Lc | 0/1/3 bytes | 数据域长度 | 命令数据域的长度(0 表示无数据域) |
Data | Lc bytes | 命令数据 | 发送给卡片的实际数据 |
Le | 0/1/2/3 bytes | 期望响应长度 | 期望卡片返回的最大字节数(0x00 表示 256) |
根据 Lc 和 Le 是否出现,APDU 分为四种 Case:
| Case | 结构 | 典型场景 |
|---|---|---|
| Case 1 | CLA INS P1 P2 | 无数据交换,如卡片复位后的首次选择 |
| Case 2 | CLA INS P1 P2 Le | 从卡片读数据,如 READ BINARY |
| Case 3 | CLA INS P1 P2 Lc Data | 向卡片写数据,如 PUT DATA |
| Case 4 | CLA INS P1 P2 Lc Data Le | 先写后读,如 SELECT + 获取 FCI |
R-APDU 响应结构
卡片返回的响应 APDU 包含两部分:
| 字段 | 长度 | 含义 |
|---|---|---|
Data | 可变 (0~Le) | 响应数据体(可选) |
SW | 2 bytes | 状态字(SW1 + SW2) |
状态字 SW1-SW2 是判断指令执行结果的关键:
| SW1 SW2 | 含义 |
|---|---|
90 00 | 指令执行成功 |
61 XX | 还有 XX 字节数据待取,需发 GET RESPONSE |
6A 82 | 文件/应用未找到 |
69 84 | 数据无效(如密钥已锁定) |
69 85 | 使用条件不满足(如未通过安全验证) |
6B 00 | P1/P2 参数错误(偏移量越界) |
6D 00 | INS 指令不支持 |
6E 00 | CLA 指令类别不支持 |
69 82 | 安全状态不满足(需先 VERIFY PIN) |
6A 82,优先检查文件 ID 是否正确;返回 69 85 大概率是卡没选上或者没做安全认证。90 00 不代表万事大吉——SW=9000 只是说"指令格式正确、执行完成",数据本身的语义验证需要你自己做。常见 APDU 命令速查
SELECT — 选择应用/文件 (INS=0xA4)
这是最常用的 APDU 命令。通过 AID(应用标识符)或文件 ID 选择卡片上的目标应用或文件。
# 通过 AID 选择应用 (P1=04 表示按名称选择)
00 A4 04 00 08 A0 00 00 00 03 00 00 00 00
# 通过文件 ID 选择 EF (P1=00 表示按文件 ID 选择)
00 A4 00 00 02 3F 00
# 选择 MF(主文件,卡根目录)
00 A4 00 00 02 3F 00 00
SELECT 成功后会返回 FCI(文件控制信息),包含文件类型、访问权限等。FCI 是 TLV 编码的,可以用卡智通的 TLV 解析器 查看结构。
READ BINARY — 读取透明文件 (INS=0xB0)
从透明结构 EF(二进制文件)中读取指定偏移量的数据:
# 从偏移 0x0000 读取 16 字节
00 B0 00 00 10
GET DATA — 获取卡片数据 (INS=0xCA)
获取卡片出厂信息、CPLC 数据、序列号等:
# 获取卡序列号 (P1P2=9F7F)
80 CA 9F 7F 00
VERIFY — 验证 PIN 码 (INS=0x20)
# 验证 PIN(P2=01 表示 PIN1, Lc=06 表示 6 位 PIN)
00 20 00 01 06 31 32 33 34 35 36
T=0 与 T=1 传输协议
ISO 7816-3 定义了两种底层传输协议:
| 特性 | T=0 | T=1 |
|---|---|---|
| 传输单位 | 字节 | 数据块(Block) |
| 错误检测 | 奇偶校验 | LRC/CRC 校验 |
| Case 4 支持 | 需发两次(先发 Lc+Data,再发 GET RESPONSE) | 原生支持 |
| 传输效率 | 较低 | 较高(适合大块数据传输) |
| 应用 | 银行卡、SIM 卡 | eSIM、高性能安全芯片 |
接触式智能卡通常两种都支持,通过 ATR(Answer To Reset)中的 TA2 字节协商选择。开发时注意 T=0 协议下 Case 4 指令需要额外处理 GET RESPONSE 流程。
实战:用 APDU 读取银行卡信息
以下是一个完整的交互序列,展示如何通过 APDU 读取一张 PBOC 借记卡的基本信息:
# 1. 选择支付系统环境 (PSE)
00 A4 04 00 0E 31 50 41 59 2E 53 59 53 2E 44 44 46 30 31 00
→ 6F 2A 84 0E ... 90 00 # 返回 FCI,SW=9000 成功
# 2. 选择应用 (AID: A000000333010101 = PBOC借记)
00 A4 04 00 07 A0 00 00 00 03 33 01 01 01 00
→ 6F 40 ... 90 00
# 3. 读取应用数据 (GPO/GET PROCESSING OPTIONS)
80 A8 00 00 02 83 00 00
→ 77 0A ... 90 00
# 4. 读取卡号记录 (READ RECORD)
00 B2 01 14 00
→ 70 1A ... 5A 08 62 24 56 78 12 34 56 78 ... 90 00
# 标签 5A 包含主账号 (PAN),值 6224567812345678
非接式通信:APDU 在 NFC 中的应用
在非接触式场景(NFC/ISO 14443)中,APDU 同样适用。区别在于底层物理层不同——非接卡通过射频磁场供电和通信,上层 ISO 7816-4 的 APDU 结构保持不变。这意味着同一张双界面卡(如银联闪付卡),接触式和非接式走的是同一套 APDU——切换物理接口不影响应用层代码。
常见问题
为什么 SELECT 返回 6A82?
最常见的原因:AID 拼写错误或长度不匹配。AID 由 RID(5字节,需向 ISO 申请)和 PIX(可变长,厂商定义)组成。检查长度字节 Lc 是否等于 AID 的实际长度。
SW1=61 是什么意思?
这不是错误!61 XX 表示卡片有 XX 字节数据等你来取。发 00 C0 00 00 XX(GET RESPONSE)获取数据。T=0 协议下 Case 4 指令最常遇到这种情况。
如何判断卡片是否支持某个 AID?
先通过 PSE(Payment System Environment)或 PPSE(Proximity PSE,AID=325041592E5359532E4444463031)查询卡片支持的应用列表。大部分支付卡都支持这个查询。