文章来源:
java前沿技术
智能卡片也可以用来保存个人记录,例如,你的医疗记录。每次你拜访一个医疗诊所,管理员就会更新你的卡片来保存当前的记录。当你无法获取你的医疗档案的时候,这个在急救的时候特别有价值。
这是两个智能有限的应用。只能卡不仅仅可以用来书写不同的应用,它还允许下载不同的应用。如果这些应用是通过JavaCard技术编写的,那么这些应用的编码和数据将会相互隔离。在Java术语中这些应用被称作在自己的沙盒里运行。
另外智能卡可以编程。这个对于卡片的发行者来说提供了十分重要的便利。例如,银行想更新这些卡片,它只需要通过连接计算机的读写器更新一下程序就可以了。下次银行的用户就会自动地通过阅读器下载程序,而不需要重新发送卡片。
关于JavaCard技术
刚开始的时候,智能卡应用的开发主要是私有的开发行为。虽然所有智能卡看起来很像,但是每个智能卡的软件都是为专门的智能卡读写器所设计的。这意味着如果A公司制造了一种智能卡,B公司也制造了一种智能卡,没有一种程序能同时在这两种卡片上运行。这个就导致只能卡的开发被限制在一个相对较小的圈子里。这些开发人员往往只能为小的卡片制造商和小的卡片发行商工作。
但是近些年,智能卡应用的开发已经不是原来的状态。现在的智能卡开发者可以开发出在多种智能卡上应用的程序。不同的应用程序可以在同一个卡片上运行。这个就是开放式的智能卡开发,它独立于卡片提供商。
JavaCard技术为Java程序员提供了一种开放式开发构架。这个技术可以同样被用来开发其他设备的应用,特别是那些小内存的应用。例如:拨号用户身份证模块(subscriber identity module,SIM)。SIM卡是一种更小更底层的卡片。典型地,SIM卡比其他智能卡有更多的内存。
Java Card技术由以下部分协议组成:
应用程序接口( application programming interface,API)。API协议指定了JavaCard的核心类库。
虚拟机。虚拟机协议指定了适合于JavaCard协议的虚拟机的特点。
运行环境。JavaCard运行环境( Java Card Runtime Environment,JCRE)协议指定了更细致的行为,例如内存管理,安全的加强。
一点JavaCard的历史
Java Card 1.0最初是由工程师 Schlumberger提出。它最初只有API协议。后来,其他公司,例如:Bull和Gemplus,参加到Schlumberger中来,并形成Java Card Forum。这个是一个工业社团。他们主要为将JavaCard技术运用到智能卡技术而努力。{zh1}Sun也参与到Java Card Forum中来,和其他智能卡工业一起开发出Java Card 2.0。这个部分包含了JCRE协议。
Java Card 2.1.1, 是{zx1}的版本,包括了API、虚拟机和JCRE协议。现在可以免费下载。
同样可以下载Java Card 2.1.1 Development Kit。这个开发攻击提供了一套完整的测试、转换工具。它可以将JavaCard应用下载到智能卡中(或者到一个应用JavaCard2.1或更高的设备中)。它同样包括了一些JavaCard的应用。
APDU
Java Card技术是智能卡协议(ISO7816)中的一个模块。这个标准指定了主机应用和智能卡之间通过Application Protocol Dat Units进行数据交换。一个APDU是一个数据包。它符合一定的格式。它有两种形式:命令APDU和响应APDU。
一个命令APDU是有一个头和可选的体组成。头包含了一个智能卡可行操作。体中包含了该请求的相关数据;它同样要指明回应该命令的{zd0}数据长度。
一个响应APDU是由一个可选的体开始,它包含了任何响应的数据。响应APDU以两个强制的字节结尾,它指定了卡片的处理状态。
查看APDU formats来了解更详细的命令和响应格式。
Java Card技术,主机应用发送命令APDU,和JavaCard应用响应APDU。(事实上,JavaCard应用一直处于闲置状态,知道接收到一个命令APDU)但是通讯并不是直接地发生在主机应用和JavaCard应用之间。而是由JCRE来充当中间角色。命令APDU是先传输到JCRE,它将负责将APDU传送到合适JavaCard应用做处理。在处理APDU之后,JavaCard应用将APDU传送给JCRE,它将发送给主机应用。
应用举例
既然智能卡的微型处理器可以编程,你可以通过编程来实现一些普通信用卡所不能实现的功能。例如:你可以使用智能卡来实现“随时随地付款”。一种服务就是收取过桥费。这里你可以购买一种卡片,它里面已经预先保存了一些钱的数值。当你每次通过收费站的时候,一个扫描器将读取当前的卡片当前的钱数(这个卡片也许会安装在你的仪表盘上),并扣从卡片中扣除当前的过桥费用。当你当前的卡片费用不够的时候,你可以购买新的卡片,或者重新增加一些钱数。
智能卡片也可以用来保存个人记录,例如,你的医疗记录。每次你拜访一个医疗诊所,管理员就会更新你的卡片来保存当前的记录。当你无法获取你的医疗档案的时候,这个在急救的时候特别有价值。
这是两个智能有限的应用。只能卡不仅仅可以用来书写不同的应用,它还允许下载不同的应用。如果这些应用是通过JavaCard技术编写的,那么这些应用的编码和数据将会相互隔离。在Java术语中这些应用被称作在自己的沙盒里运行。
另外智能卡可以编程。这个对于卡片的发行者来说提供了十分重要的便利。例如,银行想更新这些卡片,它只需要通过连接计算机的读写器更新一下程序就可以了。下次银行的用户就会自动地通过阅读器下载程序,而不需要重新发送卡片。
安装应用
Wallet是JavaCard 2.1.1开发工具包中的一个应用的例子。你可以找到它的源程序,Wallet.java,在samples目录下。或者你可以点这儿来查看原代码。Wallet应用将智能卡转换为一个电子钱包。就象一个钱包一个智能卡应用可以装钱,虽然是数字化的钱数。这个应用可以从钱包中增加或者减少钱数。它同样可以指示当前的钱包中的货币数目。当然钱包需要保护,而且只能是所有者(或者其他拥有授权的人)可以得到钱。因为这个,Wallet应用中也包含了一个安全保护机制。它要求用户输入个人身份号码(Personal Identification Number,PIN)。只有输入了合适的PIN,才可以执行相关的请求。
以下的章节将指导你整个的Wallet代码细节。
声明包
你可以捆绑相关的Java类和接口到包中,你可以捆绑相关的JavaCard应用到包中。你可以通过使用package语句来实现。实际上JavaCard技术是跟随Java语言设立的。以下的语句指定Wallet为其中的一个数据包:
package com.sun.javacard.samples.wallt;
引入JavaCard构架
JavaCard技术定义了一系列的类和借口供JavaCard应用程序使用。这些类和接口提供各种包。其中一个包就是javacard.framework。它定义了开发JavaCard应用的主要类和接口。例如:基类Applet。以下的语句引入javacard.frameword:
import javacard.framework.*;
扩展基类Applet
javacard.framework包定义了类javacard.framework.applet。它是是所有JavaCard应用的基类。javacard.framework.applet定义了一系列的方法,可以通过JCRE协议来实现通讯。所有的JavaCard应用都通过扩展这个基类来实现,就像Wallet这个应用一样:
public class Wallet extends Applet
在参考章节中包含了所有的列表:
申明变量
Wallet申明不同的变量。一些变量是一个字节的APDU(Application Protocol Data Units)变量。APDU是智能卡和设备之间交换的协议包。APDU是智能卡的通讯标准。它有两种形式:命令APDU,它指定智能卡的操作方式;响应APDU,它包含了智能卡的响应(状态和选择,数据等等)和可选的请求。
如果你参考APDU Formats,你将注意到命令APDU的{dy}个字节是CLA字节。CLS代表class of instruction。这个CLA的字节表明了APDU的整体状况。ISO7816协议为每一类APDU命令(例如:SELECT APDU命令)指定了专门的值。SELECT APDU命令值必须为0。虽然ISO7816并没有指定其他类型APDU命令的数值,但是它指定了一系列命令所需要遵守的协议。因此对于APDU命令类别,除SELECT命令之外,你可以任意选择APDU命令的值,只要它符合ISO的协议。例如对于Wallet应用,0xb0是被来表明是PROCESS类别的APDU命令。这意味着,一些操作例如credit和debit,他们的CLA字节必须有0xb0这个值。
// code of CLA byte in the command APDU header
final static byte Wallet_CLA =(byte)0xB0;
APDU的第二个字节是INS字节。这个字节指定一个协议的结构,例如,指定处理请求的类型。你可以自由地选择INS字节的数值。在Wallet应用中,0x20,0x30,0x40,0x50都分别被指定为PIN效验,credit,debit和取得当前的结余。
// codes of INS byte in the command APDU header
final static byte VERIFY = (byte) 0x20;
final static byte CREDIT = (byte) 0x30;
final static byte DEBIT = (byte) 0x40;
final static byte GET_BALANCE = (byte) 0x50;
其他常量设置credit和debit的处理限制。常量MAX_BLANCE设置{zd0}的余额为#32,767(也就是{zd0}的16进制数0x7fff)。MAX_TRANSACTION_AMOUNT设置credit和debit处理的{zd0}数值为$127。另外还有一些常量是控制无效PIN的次数(在PIN锁定之前)和PIN的{zd0}长度。
// maximum balance
final static short MAX_BALANCE = 0x7FFF;
// maximum transaction amount
final static byte MAX_TRANSACTION_AMOUNT = 127;
// maximum number of incorrect tries before the
// PIN is blocked
final static byte PIN_TRY_LIMIT =(byte)0x03;
// maximum size PIN
final static byte MAX_PIN_SIZE =(byte)0x08;
{zh1}的一些常量是返回应用的状态,例如:PIN效验失败。作为APDU协议的一部分,这些常量从应用提交到JCRE,然后再到主机应用。
// signal that the PIN verification failed
final static short SW_VERIFICATION_FAILED = 0x6300;
// signal the the PIN validation is required
// for a credit or a debit transaction
final static short SW_PIN_VERIFICATION_REQUIRED = 0x6301;
// signal invalid transaction amount
// amount > MAX_TRANSACTION_AMOUNT or amount < 0
final static short SW_INVALID_TRANSACTION_AMOUNT = 0x6A83;
// signal that the balance exceed the maximum
final static short SW_EXCEED_MAXIMUM_BALANCE = 0x6A84;
// signal the the balance becomes negative
final static short SW_NEGATIVE_BALANCE = 0x6A85;
声明成员变量
Wallet应用声明了两个成员变量,他们包含了特殊对象的值。变量pin是OwnerPIN对象,用来保存用户的PIN值。OwnerPIN是在javacard.framework中定义的类。这个类提供了一些有关PIN的操作,例如:更新和效验PIN。变量balance指示当前电子钱包中的钱的数目。
/* instance variables declaration */
OwnerPIN pin; short balance;
指定一个构造函数
一个JavaCard应用是通过应用中的install方法来创建实例的。当install应用运行的时候,它将引起一个构造函数。这个构造函数将做三个事情:创建OwnerPIN对象,初始化这个对象,并且注册这个应用的实例。构造函数被声明为private。这意味着没有其他的类可以初始化这个应用。
private Wallet (byte[] bArray,short bOffset,byte bLength)
{
// It is good programming practice to allocate
// all the memory that an applet needs during
// its lifetime inside the constructor
pin = new OwnerPIN(PIN_TRY_LIMIT, MAX_PIN_SIZE);
// The installation parameters contain the PIN
// initialization value
pin.update(bArray, bOffset, bLength);
register();
}
// end of the constructor
注意到有关内存分配的注释。虽然不是必要的,但是推荐所有在JavaCard应用中创建的对象都应该在应用构造函数中初始化。防止运行时的内存益出。
同样注意到OwnerPIN的初试化用到了两个参数:{zd0}的尝试次数和{zd0}的PIN大小。回想PIN_TRY_SIZE是3,MAX_PIN_SIZE是8。update方法是类OwnerPIN类中定义的。它将设置一新的PIN值,并且设置PIN的{zd0}尝试次数。
在JavaCard应用可以运行之前,它需要注册到JCRE。Wallet构造函数中的确调用了register函数,一个定义在javacard.framework.Applet中的函数。
javacard.framework.Applet;
识别应用
ISO7816标准指定每个智能卡应用必须能够通过应用识别标志(application identifier AID){wy}的识别 。AID是一个字节数组。头五个字节是资源标识(resource identifier RID);剩下的字节(可以0到11个字节)是私有标识扩展(proprietary identifier extension PIX). ISO指定为申请者,例如:智能卡的制造厂家;申请者可以自由选择他们自己的RID。
在Java Card技术中,AID是用来标识JavaCard应用和JavaCard应用程序的包。当有人插入一个JavaCard到一个接收设备中的时候,设备中的应用程序会向卡片发送一个命令。这个命令标识所需要执行了操作和执行该应用操作的AID。