从 本 文 开 始, 我 们 陆 续 刊 登 一 系 列 在 智 能 卡上 进 行Java 开 发 的 文 章,
以 此 把 智 能 卡 向 您 作 一 个 基 本 的 介绍。 只 要 有一 块 智 能 卡、 一 个 读 卡
机 和 一 套 可 与 智 能 卡 通 信 的软 件, 你就 可 以 开 始 进 行 实 用 应 用 程 序 的
开 发 了。 本 文 介 绍的 内 容 包括: 遵 循ISO7816 标 准 的 智 能 卡 管 理 软 件; 如 何
使 用Gemplus 阅 读器 和Gemplus 智 能 卡 从 智 能 卡 中 读 写 内 存; 一 些 利 用 智
能 卡 的 存储 功 能 的 应 用 程 序。 以 后 的 文 章 将 介 绍 不 同 厂 家 生产 的 智 能卡,
并 且 还 将 涉 及 智 能 卡 的 标 准。
作 为 专 题 系 列 的 第 一 篇, 本 文 将 主 要 为 以 后的 讨 论 作一 个 铺 垫 工 作。 在 此,
我 们 将 讨 论 一 个 称 为OpenCard的 新 标 准。
以 后 的 文 章 将 涉 及 安 全 智 能 卡 和 电 子 钱 包。 最 后,我 们 将 向您 介 绍 智 能 卡 软
件 的 基 本 框 架 结 构。
无 论 是 在 四 月 份 的JavaOne 大 会 上( 与 该 技 术 有关 的 四 次演 讲), 还 是 在 巨 大
的 网 络 新 闻 站 或 是CNN, 智 能 卡掀 起 了 轩然 大 波。 在 本 文 里, 我 们 将 以 实 用 智
能 卡 实 例 向 您展 示 真 正的 智 能 卡。 这 里 的 技 术 将 允 许 你 开 发 智 能 卡Java 应 用
程 序。
我 们 的 讨 论 焦 点 主 要 集 中 在 两 种 智 能 卡 之上: 存 储 智能 卡, 它 可 以 被 看 作 带
有 可 选 安 全 级 别 的 小 型 可 读写 磁 盘;
处 理 器 卡, 它 可 以 被 看 作 带 有 一 个 输 入 输 出 端 口 的迷 你 型 计算 机。 以 后 的 文 章
将 更 为 深 入 的 介 绍 处 理 器 卡。
本 文 的 精 华 之 处 在 于, 我 们 将 为 读 写 智 能 卡创 立 一 个简 单 的 原 形。 我 们 要 讨 论
一 种 医 药 处 方 卡, 它 将 替你 保 存 所有 的 药 方 清 单, 并 检 查 保 险、 处 方 计 划 等 等 有 用 的
信 息。 并且 我 们 将 围 绕 处 方 卡 扩 展 开 去。在 这 一 系 列 的 文 章 之 中, 你 会 注 意 到 伴 随 智
能 卡 的 一个 常 见 主 题, 那 就 是 安 全 性 问 题。 这 里 所 说 的 安全, 主 要 是防 止 通 过 卡 的 滥
插 入 或ActiveX 组 件 等 手 段 非 法 获 取数 据。 为 此目 的, 本 文 中 关 于 读 写 智 能 卡 中 数 据 的
范 例 将 给 你提 供 一 个安 全、 一 致 且 具 可 移 植 性 的 存 储。
智 能 卡 是 什 么
你 可 以 把 智 能 卡 当 作 一 个 带 有 大 脑 的 信 用卡。 其 大 脑
就 是 一 个 小 的 嵌 入 式 计 算 机 芯 片。 这 种 芯 片 可 以 被
编 程 执 行某 项 任 务 或 是 存 储 一 些 数 据, 但 应 时 刻 牢 记: 该 种
芯 片 只 不过 是 小 型 的, 它 的 处 理 能 力 绝 对 比 不 上 你 的 桌 面 计
算 机。
目 前, 智 能 卡 仅 仅 用 于 电 话、 运 输、 银 行 和 保健 等 行 业
, 但 是 感 谢 众 多 的 开 发 者, 在 不 久 的 将 来, 我 们 就
会 看 到 智能 卡 应 用 于Internet 应 用 程 序 之 中。 智 能 卡 已 经 在 日
本 和 欧 洲广 为 应 用, 并 且 在 美 国 受 到 了 欢 迎。 事 实 上, 在 美 国
的 智 能 卡业 界 最 近 共 发 生 了 三 件 颇 具 意 义 的 事 件:
PC/SC
Microsoft 联 合 其 它 几 家 公 司 推 出 了 称 为PC/SC 的
智 能 卡 应用 程 序 标 准, 用 于Win32 平 台 的 个 人 计 算 机 与 智 能 卡
之 间 实 现互 通 信。PC/SC 目 前 不 支 持 非Win32 的 系 统 平 台, 或 许
Microsoft 永 远也 不 会 那 样 做。 稍 后 我 们 将 对 此 详 加 讨 论。
OpenCard 框 架OpenCard 是 一 个 开 放 式 的 标 准, 它 支 持 智 能 卡
应 用 程 序在 网 络 计 算 机、POS、 桌 面 和 膝 上 计 算 机 等 平 台 之 上
实 现 互 操作。OpenCard 许 诺 提 供100% 纯Java 的 智 能 卡 应 用 程 序。 通
常 智 能 卡应 用 程 序 不 能 完 全 借 助 于 纯Java, 因 为 它 们 必 需 与
外 设 互 通信 或 是 利 用 客 户 之 上 的 程 序 库。( 当 然, 没 有
OpenCard, 我 们 仍然 能 够 使 用100% 的 纯Java, 但 是, 智 能 卡 的 开 发 者 必 需
从 头 定 制一 个 接 口。)OpenCard 还 提 供 了 一 个 到PC/SC 的 接 口, 使
得 开 发 者得 以 使 用 现 有Win32 平 台 上 的 设 备。
JavaCard
JavaCard 最 初 由Schlumberger 提 出, 目 前 已 被JavaSoft 制 定 为
一 项 标 准。Schlumberger 目 前 在 市 场 上 只 提 供Java 智 能
卡, 而 且 该公 司 是 第 一 个 获 得JavaCard 许 可 的 厂 商。 作 为 一 项 极
有 潜 力 占踞 统 治 地 位 的 智 能 卡 标 准,JavaCard 包 括 了 标 准 的 类
库 和API,使 得Java 小 应 用 能 够 直 接 运 行 在 遵 循ISO7816 标 准 的 智
能 卡 之 上。JavaCard 对 不 同 的 应 用 程 序 提 供 安 全 和 与 芯 片 无 关
的 运 行 环境。
注 意:
尽 管 本 文 集 中 于 智 能 卡 主 题, 但 更 为 重 要 的是 你 决 不应 囿 于 这 一 种
设 备 之 上。 从 我 个 人 角 度 将, 我 更 为偏 爱DallasSemiconductor 生 产
的揑button?设 备。 它 象 一 个 小 型 便携 的 信 用卡 一 样, 但 是 更 为 易 用。
为 什 么 呢 ? 因 为 你 不 再 需要 拿 出 钱包 从 几 张 卡 中 选 出 要 用 的 那
一 张,Ibutton 就 在 你 的 手中。 对 了, 它 是 一 枚 指 环。尽 管 存 在 无 接 触
型 的 智 能 卡( 关 于 这 方 面 的信 息 见 下文), 我 认 为Ibutton 这 样 象 珠
宝 饰 品 一 样 的 产 品 一 定会 有 利 可图。 关 于Ibutton 详 情 请 见 参 考 资 料。
顺 便 说 一 句, 八月 份 在 纽约 的Java Internet Business Expo(JIBE) 展 会 上,
Java CommerceTeam 展 示 了揓avaRing敗?/P>
为 什 么 使 用 智 能 卡 ?
使 用 智 能 卡 有 何 好 处 呢 ? 好, 下 面 回 答 这 个
问 题:
1. 智 能 卡 比 磁 卡 更 为 可 靠
2. 智 能 卡 能 够 存 储 数 百 倍 于 磁 卡 的 数 据
3. 智 能 卡 比 磁 卡 更 难 于 被 破 坏
4. 智 能 卡 可 以 被 处 理 或 是 回 收
5. 智 能 卡 在 工 业 上 可 用 的 范 围 广 阔, 并 可 提供 多 种 功
能
6. 智 能 卡 与 便 携 的 电 子 设 备 兼 容, 比 如 说 电话、PC 或 是
个 人 数 字 助 手(PDA)
7. 智 能 卡 在 不 断 的 发 展( 毕 竟 它 内 部 包 含 了一 块 计 算
机 芯 片)
智 能 卡 的 种 类
正 如 前 面 所 述, 本 文 将 集 中 讨 论 两 种 类 型 的智 能 卡:
存 储 和 处 理 器 型。 但 是 目 前 共 有 五 个 类 型 的 智 能
卡:
存 储 智 能 卡
处 理 器 智 能 卡
电 子 钱 包
安 全 卡
JavaCard
智 能 卡 是 硬 件 的 便 携 部 分, 它 必 须 借 助 于 其它 设 备 才
能 获 取 对 某 种 显 示 设 备 或 是 网 络 的 访 问。 可 以 将 卡
插 入 读 卡器, 这 通 常 称 为 智 能 卡 终 端; 也 可 通 过 射 频 无 线 电
波 来 实 现。
智 能 卡 以 下 面 两 种 方 式 与 阅 读 器 或 是 接 收 器互 通 信:
接 触 智 能 卡: 当 智 能 卡 前 端 的 芯 片 与 阅 读 器相 接 触 时
, 两 者 之 间 才 传 递 信 息。
无 接 触 智 能 卡: 这 种 信 息 传 递 通 过 天 线 来 进行, 省 去
了 手 工 插 入 或 拔 出 智 能 卡 的 动 作。 有 了 无 接 触 型
卡, 你 仅 须走 近 阅 读 器, 然 后 的 信 息 传 递 将 自 动 进 行。 这 种 类
型 的 智 能卡 可 用 于 对 速 度 要 求 较 高 或 是 插 入 拔 出 并 不 可 行 的
应 用 环 境。
一 些 厂 商 对 这 两 种 类 型 的 智 能 卡 均 已 开 始 了生 产。
为 智 能 卡 应 用 程 序 创 建 开 发 环 境
为 了 开 发 智 能 卡 应 用 程 序, 你 只 需 要 这 几 件东 西: 一
个 智 能 卡 阅 读 器、 与 阅 读 器 通 信 的 软 件 、 与 插 入 阅
读 器 的 卡通 信 的 软 件, 当 然 还 要 有 智 能 卡 及 相 关 硬 件 设 备。
智 能 卡 阅 读 器为 了 与 智 能 卡 相 互 传 递 信 息, 或 是 要 开 发 一
套 在 智 能卡 上 运 行 的 应 用 程 序, 你 必 须 拥 有 一 个 阅 读 器。 这
个 阅 读 器使 应 用 程 序 能 够 从 智 能 卡 接 收 或 是 发 出 命 令。 在 市
场 上 有 许多 种 类 的 阅 读 器, 其 中 最 为 流 行 的 是serial、 PCCard 和
keyboard 模型。(Keyboard 模 型 总 是 不 断 涌 现, 我 们 期 望 大 规 模 的
PC 厂 商 能在1998 年 六 月 之 前 直 接 提 供 这 种 产 品。)
本 文 之 中 使 用serial( 串 行) 阅 读 器 支 持 设 备。
一 个 串 行阅 读 器 与 计 算 机 的 串 口 连 接。 请 注 意 这 里 提 供 的 代
码 同 样 适用 于PCCard 型 的 阅 读 器; 许 多 的 膝 上 设 备 内 置 了PCCard
的 端 口。每 一 家 厂 商 都 提 供 了 自 己 的 协 议 用 来 向 阅 读
器 输 出 数据。 一 旦 你 可 以 和 阅 读 器 交 换 信 息, 你 就 可 以 用 一
种 协 议 与智 能 卡 进 行 通 信: 即 借 助 于APDU 格 式 与 智 能 卡 互 通。
( 关 于APDU 格 式 稍 后 讨 论。) 如 果 你 想 自 己 选 购 阅 读 器, 请 参
阅 参 考 资料 中 的揋emplus smart card readers敗?/P>
与 阅 读 器 交 换 信 息 的 软 件
本 文 中 所 列 举 的 智 能 卡 需 要 配 备 一 些 面 向 对
象 的 类。
它 们 是:
遵 循7816 协 议 通 信 的ISO 命 令 类
与 阅 读 器 通 信 的 类
将 数 据 转 换 为 厂 商 特 定 格 式 的 类
用 于 测 试 应 用 程 序 的 软 件
智 能 卡 及 相 关 硬 件 设 备
正 如 本 文 前 面 所 述, 为 了 创 建 一 个 类 似 于 下面 例 子 的
应 用 程 序, 你 必 须 拥 有 智 能 卡 的 配 套 硬 件 和 几 块 智
能 卡。 你可 以 从Gemplus 和Schlumberger 等 公 司 购 买 智 能 卡 开 发 工
具。
如 果 你 已 经 拥 有 了 阅 读 器, 要 想 使 用 它, 还要 配 备 下
面 将 要 谈 到 的 接 口 类。 前 面 已 经 讲 过, 在 与 智 能 卡
通 信 之 前,我 们 必 须 首 先 和 阅 读 器 打 交 道。 而 且 就 象 现 存 的 许
多 种 类 的智 能 卡 一 样, 如 今 已 经 有 了 许 许 多 多 的 阅 读 器。
重 要 的 智 能 卡 标 准
智 能 卡 应 用 程 序 开 发 中 容 易 使 人 迷 惑 的 一 点是 标 准 协
议 问 题。 在 我 们 的 例 子 中 基 本 上 是 应 用 程 序 与 阅 读
器 通 信,然 后 由 阅 读 器 以 一 种 标 准 协 议 与 智 能 卡 通 信。 而 这
种 标 准 是国 际 标 准 化 组 织 的7816 协 议。
象 其 它 许 多 新 技 术 一 样, 关 于 智 能 卡 有 许 许多 多 令 人
眼 花 缭 乱 的 技 术 标 准。 对 于 下 面 这 些 标 准 形 成 初 步
的 了 解 之后, 你 就 会 大 体 上 掌 握 智 能 卡 应 用 程 序 设 计 的 基 本
技 术 要 点。 当 然 对 于 一 些 系 统 的 特 殊 标 准 还 须 另 外 掌 握。 我
把 这 一 向、 整 套 标 准 分 成?横 向 的?和?纵 向 的?两 个 部 分:
横 向 的 标准 可 以 被 所 有 的 应 用 程 序 所 用, 而 纵 向 的 标 准 仅 仅
适 用 于 特定 的 系 统。
横 向 的 标 准
ISO 7816-- 描 述 到 智 能 卡 底 层 接 口 标 准。 这 种 标 准 定义 智 能 卡
阅 读 器 和 智 能 卡 之 间 如 何 传 递 字 节 流。
PC/SC-- 定 义 运 行Win3.1/Win95/NT 的 机 器 与 智 能 卡 之 间 通
信 的 标 准。
OCF-- 定 义 从Java 应 用 环 境 和 智 能 卡 之 间 的 通 信 标 准,该 标 准 完
全 是Java 接 口。( 很 快,OCF 将 允 许 开 发 者 向OCF 输 出,并 执 行 转
换, 这 样 开 发 者 再 无 必 要 使 用PC/SC 了。)
JavaCard-- 描 述JavaCard 和 它 所 支 持 的 标 准。纵 向 的 标 准
Mondex-- 以 智 能 卡 形 式 实 现 的 数 据 现 金。Mondex 不 允 许存 在 于 卡
片 之 外 的 现 金。
VisaCash-- 这 种 借 贷 卡 可 以 用 于 跟 踪 服 务 器 上 的 卡。
Proton-- 另 外 一 种 形 式 的 电 子 货 币 卡
MPCOS-EMV-- 这 是 一 种 通 用 的 智 能 卡, 它 允 许 你 实 现 自己 的 货 币
或 是 令 牌。
我 自 己 常 常 感 觉 到 疑 惑 不 解: 对 于 这 样 一 块小 小 的 塑
料 卡 片, 为 什 么 会 有 如 此 之 多 的 文 档 描 述 其 标 准,而 且 开 发
者 又 要 掌 握 大 量 的 知 识 才 能 去 开 发 它 ?
因 为 进 行 智 能 卡 的 开 发 要 求 高 度 的 专 业 知识, 所 以 市
场 上 需 要 支 持Beans 的 产 品, 这 种 产 品 应 该 用 横 向 的
标 准 去 实现 纵 向 标 准 的。 这 意 味 着 你 可 以 使 用 各 式 各 样 的 横
向 标 准 组合 开 发 出Beans 产 品 来, 就 象OpenCard 一 样, 为 了 实 现 特
定 的 一 个应 用 程 序 而 采 用 其 它 几 家 商 用 标 准 或 是 其 它 的 应
用 程 序。
Java 小 应 用 或 是Java 应 用 程 序 与 智 能 卡 之 间 的 通 信
你 知 道 了 如 何 将 所 有 硬 件 连 接 在 一 起。 现 在我 们 需 要
如 何 使 用 一 些API, 这 些API 可 以 从 应 用 程 序 向 智 能 卡
阅 读 器 发出 命 令。( 阅 读 器 然 后 与 智 能 卡 打 交 道, 作 为 一 个
应 用 程 序到 智 能 卡 之 间 的 信 息 传 递 媒 介。) 智 能 卡 阅 读 器 移
动 其 与 智能 卡 接 触 的 金 属 尖 端 传 递 数 据。 智 能 卡 对 数 据 做 出
处 理 之 后反 还 给 阅 读 器, 而 阅 读 器 再 将 之 传 会 应 用 程 序。 下
面 的 问 题是, 在 这 些 数 据 从 应 用 程 序 流 向 智 能 卡 之 时, 它 们
究 竟 处 于何 处 ?正 如 前 所 述, 应 用 程 序 与 阅 读 器 通 信, 而 阅
读 器 将 使用 上 面 介 绍 的 标 准 再 与 智 能 卡 通 信。 基 本 上, 随 着
智 能 卡 技术 的 发 展,ISO 推 出 了 一 套 智 能 卡 标 准。 该 标 准 定 义
了 智 能 卡的 机 械 和 电 器 特 性 以 及 与 智 能 卡 通 信 的 标 准。 与ISO
该 标 准 相关 的 文 档 列 在 参 考 资 料 当 中。 不 幸 的 是,ISO 没 有 能
够 提 供 与阅 读 器 相 互 通 信 的 标 准。 因 此, 为 了 向 智 能 卡 发 出
一 条 命 令, 首 先 你 要 找 出 智 能 卡 支 持 的 命 令 集 合, 将 该 命 令
用ISO 命 令包 封 装, 然 后 将 这 个 包 再 以 适 合 于 阅 读 器 的 格 式 封
装。 下 面的 例 程 正 是 完 成 所 有 这 些 琐 事。
Application Procotols Data Units(APDUs)
与 智 能 卡 交 换 信 息 的 基 本 单 元 就 是APDU 包。 从应 用 程 序
层 传 出 的 命 令 消 息, 加 上 从 智 能 卡 返 回 到 应 用 程 序
的 回 应 消息 均 称 为Application Procotols Data Units(APDU)。 与 智 能 卡
和 阅 读 器的 通 信 以APDU 形 式 实 现。 一 个APDU 包 可 以 看 作 包 含 完
整 指 令 或是 回 应 的 数 据 包。 为 了 提 供 这 样 的 功 能, 在ISO7816 规
范 家 族 里有 一 部 分 为APDU 定 义 了 一 个 良 好 的 结 构。
APDU 包 含 如 下 域:
命 令APDU 格 式 CLA INS P1 P2 Lc Data Le回 应APDU 格 式 Data SW1 SW2
下 面 是 一 些 支 持APDU 传 输 的 类 及 其 功 能 描 述:
Command-- 封 装 命 令APDU
Response-- 封 装 回 应APDU
ISOCardReader-- 规 定 一 个 接 口。 每 一 种 设 备 必 须 实 现 该
接 口
ISOCommand-- 构 成 一 个ISOCommand 并 从ISOCardReader 接 口 执 行
该 命 令与 智 能 卡 通 信
Sun 开 发 了Java Electronic Commerce Framework(JECF),
这 是 对 核心Java 平 台 的 扩 展, 它 允 许 开 发 者 轻 松 快 速 的 开 发 商
用 电 子 应用 程 序。JECF 提 供 几 种 与 智 能 卡 通 信 的 类。
我 们 这 里 讨 论 的 智 能 卡 分 别 有 一 条 读 取 数 据和 写 入 数
据 的 命 令。 它 是 由GemPlus 提 供 的 名 为GFM 卡。 你 也 可 以使 用 其 它
类 型 的 智 能 卡, 只 要 它 们 支 持ISO7816 标 准 并 且 你 了解 它 们 的A
PDU 命 令 格 式。 当 然 还 要 做 一 点 程 序 工 作。GFM 卡 的 内存 是 以64
个 比 特 或 是8 个 字 节 为 单 位 的。 你 必 须 用 模8 的 算 法读 写 数 据。
换 句 话 说, 你 不 能 向GFM 卡 做 一 次 长 度 为1k 连 续 的 写入。 我 们
这 里 提 供 的Java 代 码 完 成 这 项 功 能。 一 些 新 的 智 能 卡支 持 更 大
单 位 的 读 写 单 位。 因 此, 为 了 写 入 字 符 串?123456789敚?你 必 须
发 出 两 条 适 当 编 址 的 命 令。( 是 的, 智 能 卡 就 是 这样 难 于 编
程。) 当 存 储 型 卡 和 处 理 器 型 卡 相 互 融 合 时, 这 种 限制 也 许 会
消 失。
为 了 读 取 上 面 那 条 字 符 串, 你 应 该 发 出搑ead?命 令。 这
两 种 命 令 按 照APDU 的 术 语 被 格 式 化 的 写 在 了 下 面。在 我 们 的
例 子 中 利 用 了Java 读 写 智 能 卡。 下 面 表 中 的 值 示 出 如何 组 成 一
个APDU。 在GCM 编 程 指 南 中 定 义 了APDU 的 结 构。
Location of data Upper Lower
256 0x00 0x00
1023 0x00 0x00
3093 0x00 0x00
搖pper?和搇ower?是 地 址 的 高 位 和 低 位 字 节。
举 几 个 例子 可 能 会 有 助 于 明 晰 概 念。 这 张 表 的upper 和lower 值
提 供 了 存储 数 据 的 确 定 地 址。 我 们 讨 论 过 的 向GPM896 智 能 卡 通
信 的 两 种方 法 是:
ISOCommand(0,0xD0,0,upper,lower,8);//Write 8 bytes tothe address
ISOCommand(0,0xB0,0,upper,lower,8);//Read 8 bytes from
the address
浏 览 器 与 智 能 卡 之 间 的 通 信
三 个 本 地 接 口 的 存 在 表 明 对 主 要 的 开 发 者 集团 缺 乏 了
解, 没 有 能 够 充 分 考 虑 如 何 向 处 于Java 开 发 环 境 的
开 发 者 们提 供 简 单 易 于 记 忆 的API。 如 果 所 有 的 销 售 商 均 支 持
JNI, 至 少接 口 可 保 持 一 致, 你 不 必 化 大 量 的 时 间 去 把 接 口 绑
定。 当 然你 必 须 书 写 少 量 的 本 地 代 码, 但 拥 有 统 一 的 接 口 还
是 有 价 值的。 我 尝 试 了 所 有 三 种API, 最 终 发 现JNI 要 比 其 它 的
更 为 一 致, 并 且 也 最 为 简 单、 易 于 实 现。 联 合HotJava 一 块 使 用
是 最 佳 的, 这 样 你 可 以 对 与 串 口 通 信 的 类 签 名, 然 后 安 全 的
使 用 它 们, 比 起 另 外 两 种 浏 览 器 来 讲 麻 烦 要 少 的 多。Sun 最 近
还 宣 布 帮助 浏 览 器 公 司 实 现 新 版JDK/JVM 的 建 议。
前 面 的 讨 论 围 绕 如 何 与 一 个 不 支 持JDK 的 硬 件设 备 通 信
。 在 下 面 的 几 篇 文 章 里 我 们 将 不 再 使 用?本 地 接口敚?而 是 使
用 一 个 工 业 标 准 与 智 能 卡 通 信。 我 所 选 择 的 这 项 标
准 就 是 带有PC/SC 桥 的OpenCard 标 准。 我 将 用OpenCard 而 不 是PC/SC 书
写 应 用 程序, 为 什 么 呢 ?
作 为 开 发 者, 你 拥 有 多 种 选 择。 通 常 来 讲 这是 一 件 好
事, 但 这 也 可 能 导 致 成 本 升 高 和 功 能 的 不 一 致 性,
尤 其 是 当你 选 择 的API 并 不 被 多 种 平 台 所 支 持 时。 例 如, 你 决
定 用PC/SC 标准 书 写 支 持Win32 系 列 平 台 的 智 能 卡 应 用 程 序。 如 果
你 的 应 用程 序 是 一 个 顾 客 使 用 的 应 用 并 且 将 用 在WebTV 之 上,
你 的 选 择就 是 完 全 错 误 的。 显 示 器 上 将 会 闪 动 一 条 信 息:
?等 待WebTV 的Pentium 版 本。?智 能 卡 是 用 在Win32 桌 面 和CE 单 元 以 外
的 市 场 之上 的。 那 么 你 应 该 如 何 呢 ? 使 用OpenCard 标 准, 抛 弃 缺
乏 一 致JNI 绑 定 的Internet Explorer。 事 实 上, 我 认 为 将 所 有API 抽
象 至 单 一平 台 是 一 个 极 为 明 智 的 选 择。
实 用 的 应 用 程 序
现 在 应 该 开 始 编 写 一 个 更 具 实 用 价 值 的 智 能卡 应 用 程
序 了。 将 来, 我 们 去 看 医 生, 他 建 议 采 取 特 定 的 治
疗, 我 们 可能 处 于 如 下 场 面:
医 生 要 求 你 的 处 方 卡。
卡 被 插 入 阅 读 器, 医 生 查 看 你 以 前 的 处 方 单。( 对 于拥 有 复 杂
医 疗 历 史 的 人 来 说, 可 能 需 要 一 个 专 家 系 统。)
医 生 注 意 到 与 此 同 时 另 外 一 位 医 生 在 为 你 治 疗, 而他 们 俩 人
开 出 的 药 方 有 不 良 反 应。 因 此 目 前 这 位 医 生 就 会 向智 能 卡 输
入 另 外 一 种 药 方。( 理 想 化 的 结 果 是: 智 能 卡 可 以将 药 方 传
给 药 房。)
你 现 在 可 以 将 卡 取 出 送 到 药 房 并 插 入 那 里 的 阅 读器。
药 剂 师 读 出 你 的 药 房 单。
设 想 药 剂 师 比 医 生 更 为 了 解 药 性, 他 认 为 医 生 应 该重 新 考 虑
所 开 出 的 药 方。 药 剂 师 给 医 生 打 电 话, 而 电 话 号 码包 括 在 智
能 卡 的 记 录 之 中。 经 过 短 暂 的 讨 论 之 后, 两 个 人 达成 了 一 致
并 且 更 新 卡 中 的 记 录。
药 剂 师 填 写 你 的 药 方 单, 将 院 方 的 计 划 信 息 从 卡 中取 出, 并
用 加 密 的 协 议 与 之 通 信。
院 方 验 证 你 是 真 正 的 成 员, 药 方 出 自 授 权 医 生 之手, 并 且 适
时 更 新 卡 上 的 数 据。
药 剂 师 向 你 收 取5 美 元。
这 听 起 来 是 不 是 一 个 更 为 安 全 的 系 统 ? 当 然是 比 较 目
前 的 系 统 而 言, 现 在 基 本 上 是 纸 和 笔 的 时 代, 人 充当 彼 此 相
分 离 的 计 算 机 系 统 的 连 接 点。 事 实 上 在 德 国, 医 疗智 能 卡 已
经 在 使 用 了。
智 能 处 方 卡 的 优 点
比 较 传 统 的 处 方 计 划 卡 片 而 言, 智 能 卡 到 底带 给 我 们
那 些 好 处 呢 ? 下 面 将 它 们 一 一 罗 列 出 来:
当 你 要 改 变 卡 中 的 数 据、 出 门 旅 行 或 是 到 新 的 医 疗机 构 之 时
, 可 以 获 得 以 前 接 受 治 疗 时 开 具 的 各 种 处 方 数 据。
在 紧 急 救 护 或 是ER 工 作 人 员 需 要 时 及 时 的 提 供 过 去的 医 疗 和
护 理 历 史。
详 尽 清 晰 的 医 疗 历 史 信 息, 包 括 时 间、 地 点 和 程 度等 具 体 信
息。
可 以 有 所 选 择 的 将 数 据 提 供 给 特 定 的 人 员, 当 然 也可 选 择 从
何 处 接 受 数 据 更 新。
为 了 对 以 上 的 优 点 提 供 支 持, 我 们 需 要 开 发一 个 应 用
程 序, 允 许 我 们 用 一 种 安 全 的 方 式 向 智 能 卡 读 写 数据。 如 果
拥 有 了 硬 件 设 备, 我 们 需 要 将 特 定 的 字 符 串 写 入 或从 智 能 卡
读 出。 这 些 要 通 过 调 用CardStrings.java 中 提 供 的 方 法来 完 成。 这
些 原 形 类 的 提 供 大 大 便 利 了 对 智 能 卡 的 编 程 工 作。
我 们 还 添加 了 一 个Beans 风 格 的 事 件 处 理 器, 用 以 通 知 用 户 象
智 能 卡 的插 入 这 样 的 事 件。( 这 最 后 一 点 的 改 进 要 感 谢JECF 的
高 级 高 级开 发 人 员Dan Guinab。)
考 虑 如 下 来 自RWString.java 的 代 码 片 段:
import java.commerce.smartcards.*; Packages form JECF to supportsmart cards
import java.commerce.gemplus.*;
import java.commerce.DeviceManager.*;
import java.awt.event.*;
/**
* Read and write Gemplus Memory cards. The following cards
* are supported:
* GFM 4k
*/
public class RWString {
public static void main( String args[]) {
WriteString ws = new WriteString(args);
}
}
class WriteString implements ActionListener {
ISOCardReader isoReader = null;
int portNumber;
String deviceName;
public WriteString(String args[]) {
////////////////////////////////////
// Process the arguments
////////////////////////////////////
for(int i = 0; i < args.length; i++) {
if ( args[i].equals("-port") ){
portNumber = 0;
} else if ( args[i].equals("-device") ) {
deviceName = new String ( args[++i] );
} else if ( args[i].equals("-help") ) {
System.out.println("Usage: string
-port # -device COM1 or /dev/ttya" );
System.exit(0);
}
}
SmartCardDetector scDetector = new
SmartCardDetector(1000);
scDetector.addActionListener(this);
scDetector.startDetection();
}
public void actionPerformed(ActionEvent actionEvent) {
System.out.println("Action Performed: " + actionEvent );
try {
// Open the requested port number
SmartCardReader scr = new SmartCardReader();
isoReader = scr.getDefault();
isoReader.beginCardSession(GemplusSerialReader.GFM);
CardStrings.writeGFMString("01234567" , isoReader );
System.out.println(CardStrings.readGFMString(isoReader ) );
isoReader.endCardSession();
} catch(Exception e) {
System.out.println( "Exception " + e);
e.printStackTrace();
} finally {
try {
isoReader.endCardSession();
} catch(Exception eFinally) {
System.out.println("Could not power
Down card perform manual reset");
}
}
}
}
CardStrings 类 提 供 了 一 些 用 于 向 智 能 卡 读 写 字符 串 的 方
法。 这 些 字 符 串 在 智 能 卡 中 的 存 储 开 始 于 两 个 字 节
的 长 度 域, 后 面 跟 着 六 个 空 的 字 节, 再 后 面 是 字 符 串 数 据。
对 于 那 些 真 正 开 始 智 能 卡 应 用 程 序 开 发 的 人来 说, 必
须 面 对 一 项 挑 战, 那 就 是 修 改Cardstring 的 方 法, 完 成
Java 对 象的 读 写。 这 种 工 作 要 比 读 写 字 符 串 来 得 更 为 灵 活。
如 果 实 现了Java 对 象 的 写 入, 你 就 不 必 考 虑 所 要 存 储 数 据 的 格
式。 我 想从 一 个 大 家 都 说 得 出 的 简 单 问 题 入 手, 即 将 字 符 串
存 储 到 智能 卡 中。
下 面 的 例 子 是 一 个 完 整 的 数 据 读 写 应 用 程
序, 它 适 用于GCR400 阅 读 器 和GemPlus GFM 智 能 卡。 仅 需 一 点 点 的 附
加 工 作 它就 可 以 支 持 其 它 类 型 的 阅 读 器。 但 你 不 必 费 心 去 做
那 样 的 工作, 因 为 下 个 月 里, 我 们 将 提 供 一 个 用OpenCard 完 成
这 种 工 作的 例 子。 这 种OpenCard 将 迅 速 成 为 这 个 行 业 中 的 标 准。
package java.commerce.MemoryCards;
import java.io.IOException;
import java.commerce.smartcards.*;
import java.commerce.gemplus.*;
public class CardStrings {
/**
* Write a String, since the card is modulo 8 and we are
* not using serialized objects -- the first two bytes are
the
* length followed by six spare bytes. Strings longer than
4096 - 48
* bits will be truncated.
*/
public static void writeGFMString(String s ,
ISOCardReader isoreader) {
ISOCommand wcmd;
ISOCardinputStream winput;
int upper,lower;
short length = (short)s.length();
// Length of the input string
System.out.println("Length is " + length );
try {
// Write the control section out
wcmd = new ISOCommand(0, 0xd0, 0, 0, 8,0);
// Save the length
wcmd.data.writeShort( length );
System.out.println("Write out the Length");
winput = wcmd.execute(isoreader,
new GemplusReaderFailureHandler());
// Write the String out
int wholeAmount = length/8;
// Groups of 8
int remainder = length % 8;
// Remainder
// Write the String out groups of 8
for ( int l = 1; l <= wholeAmount; l++ ) {
System.out.println("Writing 8 bytes at " +
(l*8));
upper = (l * 8 ) >> 8;
lower = ( l * 8 ) & 0xff;
wcmd = new ISOCommand(0, 0xd0, upper, lower,
8,0);
int index = ( (l-1) * 8 );
wcmd.data.writeString(s.substring(index),8);
System.out.println("Write out bytes at " +
index);
winput = wcmd.execute(isoreader,
new GemplusReaderFailureHandler());
}
// Write the remainder out
upper = ((wholeAmount+1) * 8 ) >> 8;
lower = ((wholeAmount+1) * 8 ) & 0xff;
wcmd = new ISOCommand(0, 0xd0, upper,
lower, remainder,0);
int index = ( wholeAmount * 8 );
wcmd.data.writeString(s.substring(index),remainder);
winput = wcmd.execute(isoreader,
new GemplusReaderFailureHandler());
} catch ( Exception e ) {
System.out.println( "Exception " + e);
e.printStackTrace();
}
}
/**
* Read a String, since the card is modulo 8 and we are
* not using serialized objects -- the first two bytes are
the
* length followed by six spare bytes. Strings longer than
4096 - 48
* bits will be truncated.
*/
public static String readGFMString(ISOCardReader isoreader )
{
ISOCommand rcmd;
ISOCardinputStream rinput;
int upper,lower;
short length;
StringBuffer sb = new StringBuffer();
try {
// Read the control section
rcmd = new ISOCommand(0, 0xb0, 0, 0, 0, 8);
// Read the length
rinput = rcmd.execute(isoreader,new
GemplusReaderFailureHandler(
));
length = (short)rinput.readShort();
System.out.println("The length is: " + length);
// Read the String
int wholeAmount = length/8; // Groups
of 8
int remainder = length % 8; //
Remainder
// Read the String in groups of 8
for ( int l = 1; l <= wholeAmount; l++ ) {
System.out.println("Reading 8 bytes at " +
(l*8));
upper = (l * 8 ) >> 8;
lower = ( l * 8 ) & 0xff;
rcmd = new ISOCommand(0, 0xb0, upper, lower, 0,
8);
rinput = rcmd.execute(isoreader,new
GemplusReaderFailureHand
ler());
sb.append ( rinput.readString(8) );
System.out.println("String to this point:" +
sb.toString());
}
// Read the remainder
upper = ( (wholeAmount+1) * 8 ) >> 8;
lower = ( (wholeAmount+1) * 8 ) & 0xff;
rcmd = new ISOCommand(0, 0xb0, upper, lower, 0, 8);
rinput = rcmd.execute(isoreader,new
GemplusReaderFailureHandler(
));
sb.append ( rinput.readString(remainder) );
System.out.println("String to this point:" +
sb.toString());
} catch ( Exception e ) {
System.out.println( "Exception " + e);
e.printStackTrace();
return ( null );
}
return ( sb.toString() );
}
}
以 后 的 文 章
在 后 面 的 文 章 里 面, 我 们 将 讨 论 这 样 一 个 问题: 医 生
如 何 能 够 对 他 加 入 你 智 能 卡 中 的 条 目 进 行 安 全 的 签
名, 这 样处 方 卡 才 能 够 发 挥 它 的 实 际 作 用。 该 应 用 程 序 还 必
须 提 供 显示 你 处 方 卡 历 史 信 息 的 功 能。 这 样 的 功 能 可 以 为 用
户 自 己 所用, 当 然 也 可 提 供 给 药 剂 师 或 是 紧 急 救 护 人 员。 再
加 上 你 过去 医 疗 历 史 带 有 警 报 色 彩 的 概 要, 以 及 外 科 手 术 和
慢 性 病 等信 息, 你 的 智 能 处 方 卡 将 会 提 供 许 多 种 应 用 前 景。
结 论
本 文 为 这 一 系 列 关 于 智 能 卡 的 文 章 做 了 一 个铺 垫 工 作
。 在JavaWorld 中 的 这 一 系 列 专 题 包 括 四 篇 文 章。 均 将由 本 文 作
者 提 供, 希 望 对 于 你 在 智 能 卡 方 面 的 应 用 程 序 开 发有 所 裨 益
。 我 将 利 用Java Electronic Commerce Framework(JECF) 作 为 构筑 使 用 程
序 的 基 础 结 构。JECF 为 简 化 与 智 能 卡 的 通 信 提 供 了 几个 类。 程
序 中 的 大 部 分 代 码 和 例 子 来 自JECF。 你 可 以 从 参 考资 料 中 找
到 下 载JECF 的 方 法, 那 之 中 已 经 包 括 了 对 智 能 卡 的 支持。