JAVA卡开发技术详解
public tjdfile mf;
// MF 对象
public tjdfile cdf;
// 当前 DF 对象
//------------------------------------------------
public tjfilesystem() {
mf = null; cdf = null;
Java Card 开发技术初探
金邦达宝嘉集团上海办事处 孟宏文 上海市银城东路101号汇丰大厦13F,200120
关键词: JavaCard,卡片操作系统(COS),智能卡
摘要
本文介绍如何优化Java卡的软件开发,及如何构造一个通用的软件类库来 针对多变的应用需求,快速开发出合乎市场需求的卡片操作系统。
} //-----------------------------------------------public boolean canRecieve() {
if ( ins is case3 command ) return true; // pcode!!! return false; } }
byte[] apduBuffer;
if (selectingApplet())
return;
apduBuffer = apdu.getBuffer();
if (apduBuffer[ISO7816.OFFSET_CLA]!= 0x90 )
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
} } //-----------------------------------------------private void fverify_pin(APDU apdu) throws ISOException {
// 取APDU 数据数组 // 检查P1,P2是否合法 // 检查Lc,data 或 Le 是否正确 // 比较 口令 // 返回结果 } //-----------------------------------------------private void fread_binary(apdu) throws ISOException { // 取APDU 数据数组 // 检查P1,P2是否合法 // 检查Lc,data 或 Le 是否正确 // 读取 文件数据 // 返回结果 } }
回来再考虑一下“应用”本身,智能卡应用都是以ISO7816为基础,然后 再添加具体的应用需求,它应有比如应用类型和状态等属性,还有处理事件(输 入数据)的方法。在做C++程序时,我们通常会设计一个纯虚类作为父类,定义 好所有的公共行为供子类重载。Java也支持纯虚类和单重派生(考虑一下为何 不支持多重派生?),如果我们将应用设计成虚类,最后的具体实现至少是第三 级子类了,因为我们肯定会将ISO标准的指令和一些通用指令放在二级类。考 虑到Java是编译型的,在虚拟机上运行时,过多的类继承将在寻址上极大的降 低程序运行的速度,毕竟Java卡的硬件不可能和PC相提并论啊!所以基类应当 设计成一个包含ISO指令及其他公共指令的不含纯虚函数的类,它不用派生子 类就可以直接运行。一个通用的、标准的、可重复构建的小型COS诞生了,它 是一个最简单的“应用”。
} public static void install(byte[] bA, short bOfft, byte bLen)
throws ISOException { new MyCOS (bA, bOff, (byte)bLen ); //创建一个类实例 } //------------------------------------------------
public boolean select() {
return true; } //-----------------------------------------------public void deselect() {
return; } //-----------------------------------------------public void process(APDU apdu) throws ISOException {
有了tjapdu后,我们可以在MyCOS.Process函数里一次将数据全部复制到 tjapdu的一个实例,然后将它传给功能函数,函数在得到输入数据并做相应处 理后,可能要返会数据,我们约定使用Le标明返回数据的长度,返回数据则放 在pdata里,这样每个函数只是按照约定将数据放入指定的域,真正返回到外 部统一在MyCos.Process里处理,这样代码效率提高很多啊,而且也不容易 出错。
将这个Appleபைடு நூலகம்编译、转换后,下装到卡上,就可以测试了。是不是很简
单?是,但这只是个例子,告诉我们一些最基本的元素。其实大多数的应用都 要创建许多文件和密钥,标准的文件有二进制文件、线性定长文件、循环文件
等等;密钥有PIN,PUK,DESKEY,RSAKEY等;要实现分层的文件管理机制,对
文件的各种操作的前提也都可定义不同的安全控制;而密钥也可以设置指定的 用途,并实现密钥管理以支持复杂的安全控制策略。在应用阶段还有要考虑应 用本身的一些逻辑和安全控制。真是很复杂啊。下面我们先看一下一个基本的 卡操作系统(COS,即我们正在讨论的Applet)的命令处理过程:
本文将介绍在开发Java卡应用时的几点体会,希望能为正在做Java卡开发 或想做这方面工作的同仁提供一点思路,开发出务实高效、结构清晰和方便维 护及可重用的Java应用。卡的基础知识、卡片操作系统和Java语言等基础知 识对理解本文是必要的,这里就不赘述了。
一、JAVA 卡应用结构的优化
Java卡应用的开发其实和其他软件开发是一样的,应用的主体是一个特殊的 Applet,特殊是因为它必须从javacard.framework.Applet这个类派生。 Java卡2.1规范定义了几个标准的包(Package),它涉及Java卡Applet基本 的接口与工具、安全机制和加密等方面的接口函数,必须熟练掌握。Java卡仅 支持Java语言的一个子集,所以在编程时也要特别注意。VISA和其他组织也定 义了一些行业规范(Addon),对我们开发行业应用也提供了标准的安全机制和 接口。在开发Java卡的过程中,如果按照厂商提供的例子的模式去开发的话, 结构和易读性不是很好,对后期的维护和代码重用也比较困难,所以有必要对 应用结构做进一步的优化,下面先看一下这个Applet最简单的实现。
}
//------------------------------------------------
public void reset() { //复位函数必须定义,否则,嘿嘿. . .
cdf = mf;
if(cdf!=null) cdf.selected();
}
//------------------------------------------------
序言
随着智能卡的发展,Java卡已经被市场广泛认同并快速发展,成为智能卡 的发展趋势,据估计,目前全球有30%的手机SIM卡是Java卡,在金融业和其 它应用行业也发展迅速,相信会逐渐成为主流产品之一。为什么呢?因为有两 个主要原因:一是Javacard开发采用Java语言,配备了整套标准的Java卡编 程的API,使得开发人员无需了解复杂的智能卡硬件,就可以进行智能卡应用 的开发,从而大大减少开发时间和降低开发难度;二是支持一卡多用和重用。 支持一卡多用是指Java卡上可以同时存在多个不同的应用。这些应用可以来自 同一个供应商,也可以来自不同的供应商。这样一张Java卡就可以完成不同的 功能,重用是指Java卡上的应用可以根据需要进行删除或添加新的应用,而无 需更换卡片,这样就大大增强了智能卡的灵活性和生存力。
下一个要考虑的是文件系统如何实现,文件系统其实就是一个包含文件对 象、密钥、安全策略等要素的集合,它包含根目录和子目录,还有文件搜索的 方法实现,只要规划好文件系统的设计,后续的处理就会简单许多,我们暂时 不考虑密钥和安全策略的问题,先实现文件系统的类:
public class tjfilesystem {
APDU命令 ->
传 输
层
命
->
令 解
释
层
文
->
件 管
理
层
传 -> 输
层
-> APDU响应数据
图一:命令处理过程
从这个过程和Applet的实现做比较,除了没有实现文件管理,其它基本有 了雏形。似乎可以开始了,慢!在每个功能实现的函数里,都是千篇一律、几 乎相似的代码,看上去很是胸闷,运行效率估计也很低。有没有解决办法?我 们先从解决这个问题展开,首先定义一个tjapdu的类来代替标准的APDU类。
package com.goldpac.jcapp; //包名称 import javacard.framework.*; //引用的包
public class MyCOS extends javacard.framework.Applet {
protected MyCOS (byte[] buffer, short offset, byte length) { register(); //向JCRE注册自己的实例
public boolean selectByFid(byte[] pfid) {
//在当前目录下找匹配的文件,未找到则看是否为3F00
//找到返true; 否则返false
}
}
tjdfile是描述DF行为的类,它类似一个容器,包含EF、DF和密钥,当然 也应有一个“父亲”指向上层的DF,具体细节我们在后边讨论。
public class tjapdu { public byte cla, ins, p1, p2; public short lc, le; public byte[] pdata;