Javacard 不完全指北
本文旨在在尽量不出错的情况下简单介绍 Javacard 相关资讯
笔者第一次了解到 Javacard 的存在是在 tuna 的一次金枪鱼之夜分享中
智能卡相关
以下信息不仅适用于 Javacard,通常也适用于其他智能卡
智能卡芯片也有其他封装形式和电气连接方式 (如常见的 ST33 等芯片)
机械尺寸
正常 Javacard 的尺寸与银行卡相同(毕竟是同一个标准),该尺寸为 ISO/IEC 7810 中的 ID‑1 规格;卡片上的芯片触点排列和定义同样由该标准确定
在通常情况下,Javacard 的芯片仅位于芯片触点下方,NFC 通信天线嵌在卡片塑料层中,可以透过高亮度的光源观察
也有尺寸为全尺寸 SIM (1FF) 的 Javacard 售卖
通信协议
物理层
接触式通信通过与卡片上的芯片触点接触来建立连接,通信协议在 ISO/IEC 7816-3 中规定,为异步半双工同步传输协议
非接触式通信通过与卡片上的线圈电磁感应耦合来获得能量和建立连接,通信协议在 ISO/IEC 14443 中规定,工作在 13.56 MHz ISM 频段,标准中规定了两种通信机制 Type A 和 Type B,具有不同的调制、编码和防冲突方式
磁条不参与与芯片的通信,根据矫顽力不同有高抗和低抗等分类,按磁条的磁轨数有双轨、三轨等,不同磁轨的编码方式在ISO/IEC 7811中定义。
通常同时具有接触式和非接触式接口的卡片被称为 “双界面”,额外印刷的磁条也可能被作为一个“界面”,与其他两种的组合被称为 “双界面”或“三界面”
传输层
接触式通信采用两种传输协议:
- T=0 (面向字节的半双工传输协议)
- T=1 (面向块的半双工异步传输协议)
非接触式采用一种传输协议:
- T=CL (非接触式传输协议 Transmission = ContactLess)
传输层负责在卡片上电、初始化完成后打包上层的应用通信数据并交由物理层传输
应用层
应用层采用统一格式的 APDU (Application Protocol Data Unit) 指令进行通信,该格式在 ISO/IEC 7816-4 中描述
C-APDU
终端向智能卡发送的格式为 COMMAND APDU (C-APDU)
1 | =================================================================== |
Header 指令头 必选
- CLA (Class): 指令类别。用来区分应用类型或安全级别 (如 00 表示标准的 ISO 7816 指令,80 常常用于各家卡商的自定义指令)
- INS (Instruction): 指令码。告诉卡片要做什么 (如 A4 表示 SELECT 选择应用,B0 表示 READ BINARY 读取数据)。
- P1 / P2 (Parameter 1 & 2): 指令参数。提供指令所需的具体参数,通常用作文件偏移量、安全标志或配置选项
Body 可选
- Lc (Length of Command Data): 指示后面 Data 字段的字节长度。
- Data: 终端实际发送给卡片的载荷数据
- Le (Length of Expected Data): 终端期望卡片返回的数据最大长度 (如果填 00,通常表示期望返回最大可用长度,最高 256 字节;扩展 APDU 可达 65536 字节)
R-APDU
卡片处理完指令后,会返回一个响应
1 | ========================================= |
- Data (可选): 卡片返回的实际业务数据。它的长度由 C-APDU 中的 Le 以及卡片内部逻辑共同决定
- SW1 / SW2 (Status Word 1 & 2,必选): 状态字。用于指示指令执行的结果
通过状态字可以知道命令的执行情况
| SW1 | SW2 | 状态说明 (Description) |
|---|---|---|
90 |
00 |
成功 (Success) |
61 |
XX |
有额外数据待读取 (XX bytes remaining) |
62 |
83 |
文件已失效 (File invalidated) |
63 |
00 |
认证失败 (Authentication failed) |
63 |
CX |
认证失败,剩余重试次数为 X |
65 |
81 |
内存故障 (Memory failure) |
67 |
00 |
Lc 长度错误 (Wrong length) |
68 |
81 |
不支持的逻辑通道 |
68 |
82 |
不支持的安全报文格式 |
69 |
82 |
安全状态不满足 / 未授权 (Security condition not satisfied) |
69 |
83 |
认证方法被锁定 (Method blocked) |
69 |
85 |
使用条件不满足 (Conditions not satisfied) |
6A |
80 |
数据域 (Data) 参数不正确 |
6A |
81 |
不支持该功能 (Function not supported) |
6A |
82 |
未找到文件或应用 (File/Applet not found) |
6A |
83 |
未找到记录 (Record not found) |
6A |
86 |
P1/P2 参数不正确 |
6C |
XX |
Le 长度错误,实际应为 XX 字节 |
6D |
00 |
不支持的 INS / 无效指令码 |
6E |
00 |
不支持的 CLA / 无效指令类 |
6F |
00 |
未知内部错误 (Unknown error) |
读卡器相关
通常免驱动的智能卡读卡器为 USB CCID 设备,PC/SC 为事实 API 标准
接触式和未接触式需要不同的读卡器类型,也有同时支持两种接口的读卡器售卖。
安卓手机自带的 NFC 功能允许应用通过非接触式接口向智能卡发送和接收 APDU,可以安装 NXP TagInfo / NFC Tools 等读取卡片信息。也可以通过 HCE 功能模拟智能卡接收和响应外部读卡器发送的 APDU
Canokey 和 Yubikey 声明自己为 USB CCID 设备,以允许操作系统读取其中的 “智能卡” 实现相关功能
GlobalPlatform 相关
如果你需要了解如何管理 Javacard:进行如安装或删除 applet 等操作,或者对 Javacard 的生命周期、ISD 等感兴趣请直接阅读 CardSpecification_v2.3.1,这份文档内详细说明了卡片生命周期以及应用 (applet)、模块和安全域 (发卡方安全域 ISD、补充安全域 SSD) 和安全通道 (SCP02、SCP03) 、密钥等概念和对应的 APDU
GlobalPlatform (GP) 是一个跨行业的国际标准化组织,GlobalPlatform 制定的标准定义了如何在安全环境中安全地加载、安装、更新和删除应用程序,以及如何进行密钥管理和身份认证。不同生产厂家的 Javacard 卡通常均遵守特定版本的 GlobalPlatform 规范
如果你不了解你正在对卡进行的操作,至少以下操作是危险的,误操作或多次失败尝试可能会导致卡片变砖、锁定或不可用
- 更改卡片的生命周期状态 (单向不可逆+影响可用管理功能)
- 使用软件提供的默认密钥或猜测的密钥进行安全通道认证 (可能导致锁定)
- 替换、添加、删除密钥或添加新的安全通道 (错误的配置或组合可能导致失去管理权)
- 在不可靠的连接状态下写入卡片 (断连可能导致卡片变砖)
以下软件提供 GlobalPlatform 规范下的卡片管理功能
- GlobalPlatformPro 非常经典简洁的 CLI 工具
- PyApduTool 随 JCIDE 安装,虽然很旧但是图形界面很好用
Applet 相关
你可以自己编写或使用开源的 Applet 项目,编译得到 .cap 文件并将其加载到 Javacard 上
不同的Applet通常具有不同的AID,以在选择应用时加以区分
这部分信息可能过时,你可以参考以下链接:
- javacard-curated-list 一份非常详细的 applet 列表
- 一位安了很多 Applet 的博主的文章
卡片载入应用后,通常需要特定的应用来配套使用,你可以参考 CanoKey 帮助文档 和 网络上使用 Yubikey、Canokey 的相关博客以及下列项目中的说明文档来了解相关应用的配置和使用方法
PIV: makinako/OpenFIPS201
- 2026年4月仍在更新
- 正在进行FIPS认证
GPG: github-af/SmartPGP
- 2025年9月仍在更新
- OpenPGP 3.4
- 使用 requestObjectDeletion
FIDO2: BryanJacobs/FIDO2Applet
- 2026年4月仍在更新
- 完整覆盖 FIDO2 CTAP2.1 标准
- 需要 Javacard 3.0.5+
- 需要较多空间
GIDS: vletoux/GidsApplet
- 2023年停更
- 需要 Java Card 2.2.1+
- 初始化工具
BIP39: keycard-tech/status-keycard
- 不会用
NDEF: OpenJavaCard/openjavacard-ndef
- 还没用
MRTD (机读旅行证件): https://github.com/E3V3A/JMRTD/tree/master/passportapplet
除此之外还有HOTP/TOTP、EMV 和 SIM 等可通过 Applet 实现的功能
如何购买 Javacard
不构成购买建议
你可以在淘宝上搜索特定的 Javacard 产品型号来购买。对于 NXP 生产的 Javacard,其初始化文档为保密资料,通常需要卖家帮助完成卡片初始化操作 (卡片通信参数: ATR、历史字符等;卡片通信配置: APDU缓冲区大小、逻辑通道数、VHBR、SCP通道配置;卡片功能配置: RSA最大长度等) 或直接购买未初始化的卡片、使用卖家提供的出厂密钥自行初始化 (需要 NXP 私有 APDU 命令)
目前推荐 NXP 的 J3R 系列,比较新,而且可以买到:
- NXP J3R110 / J3R180
- NXP J3R150 / J3R200
其可用容量约为J3R后面的三位数字(单位: KB),购买时需要注意 EMV / SecID 版本的区别 (是否支持 ECC),以及接口是否为你需要的 (接触式 / 双界面 / 纯非接),还有最重要的卡片密钥
如果你对卡片购买、初始化命令感兴趣,欢迎邮件交流讨论