声明:转自-http://blog.csdn.net/chendf_20
整理了一下常用到的Java卡开发包里的方法,以后就能加快开发速度了。
//Java Card开发方法查询
import java.lang.*;import javacard.framework.*;import javacard.security.*;import javacardx.crypto.*; //该包为扩展包//install方法
public static void install(byte[] bArray, short offset, byte length){ new wallet().register(bArray, (short) (bOffset + 1), bArray[bOffset]);} /************************************************************************************///建立类JCSystem中的临时数组的方法/*每个方法调用中的第一个参数 length 指出所请求的临时数组的长度。第二个参数 event 指出哪种事件清除该对象。因此,方法调用指出临时数组的类型,CLEAR_ON_RESET 或CLEAR_ON_DESELECT。*///建立一个临时布尔数组Public static boolean[] MakeTransientBooleanArray(short length,byte event);//建立一个临时字节数组
Public static byte[] MakeTransientByteArray(short length,byte event);//建立一个临时short数组
Public static short[] MakeTransientShortArray(short length,byte event)//建立一个临时对象数组
Public static object[] MakeTransientObjectArray(short length,byte event)/*
方法 isTransient 返回一个临时类型常数(CLEAR_ON_RESET 或 CLEAR_ON_DESELECT),或者返回常数 JCSystem.NOT_A_TRANSIENT_OBJECT 指出该对象是 null 或者是一个永久对象*/public static byte isTransient(Object theObject); /************************************************************************************///原子性/*Util.arrayCopy方法保证要么所有的字节被正确地拷贝,要么目标数组被恢复为其原来的字节值。如果该目标数组是临时的,就不具有原子特性。*/public static short arrayCopy(byte[] src,short srcOff,byte[] dest,short desOff,short length);//方法arrayCopyNonAtomic在拷贝操作过程中不使用事务设施,即使一个事务正在执行之中。
public static short arrayCopyNonAtomic(byte[] src,short srcOff,byte[] dest,short desOff,short length);//用指定的值填入一个字节数组的诸元素:
public static short arrayFillNonAtomic(byte[] bArray,short bOff,short bLen,byte bValue); //事务的提交//开始一个交易JCSysten.beginTransaction();//在该交易提交之前,一组永久数据的修改中的全部修改都是暂时的//提交一个事物JCSysten.commitTransaction();//返回一个commit buffer中的字节总数
JCSystem.getMaxCommitCapacity();//返回在该commit buffer中剩下未用的字节数JCSystem.getUnusedCommitCapacity() /************************************************************************************/javacard.framework.Applet 中的方法//JCRE调用这个静态方法建立Applet子类的一个实例Public static void Install(byte[] bArray,short bOffset,byte bLength)//示例public class WalletApp extends Applet{ private log transaction_log;private byte[] wallet_id;private byte wallet_balance;public static void install(byte[] bArray, short bOffset,byte bLength){new WalletApp();
}
private WalletApp(){ //建立一个具有指定事物记录数的事物日志 transaction_log = new Log(TRAN_RECORD_NUM); //建立一个字节数组用以存储钱包wallet的ID wallet_id = new byte[ID_LENGTH]; //初始化钱包wallet的余额 wallet_balance = INITIAL_BALANCE; //向JCRE注册该applet实例 register();}}//安装参数处理示例
private walletApp(byte[] bArray,short bOffset,byte bLength){ //建立一个事物日志并指出最大的日志记录数 max_record_num = bArray[bOffset]transaction_log = new Log(bArray[bOffset++]);//设置钱包IDwallet_ID = new byte[ID_LENGTH];Util.arrayCopy(bArray,bOffset,wallet_id,(byte)0,ID_LENGTH);//bOffset前进ID_LENGTH个字节bOffset += ID_LENGTH;//初始化钱包余额wallet_balabce = bArray[bOffset++];//检查AIDbyte AID_len = bArray[bOffset++];if (AID_len = =0){ //利用缺省AID向LCRE注册applet实例 this.register();}else{ //利用安装参数中指出的AID向JCRE注册applet实例 //bArray中的AID字节从索引bOffset开始,由AID_len个字节组成 this.register(bArray,bOffset,AID_len);}} //该方法由applet用来向JCRE注册本applet实例并指定CAP文件中的缺省AID给本applet实例Protected final void Register()//该方法由applet用来向JCRE注册本applet实例并将数组bArray中指出的AID赋予该applet实例。
Protected final void Register(byte[] bArray,short bOffset,byte bLength) /************************************************************************************///JCRE调用这个方法通知该applet它已经被选择。Public boolean Select()//JCRE调用这个方法指示该applet处理一个输入的APDU命令。
Public abstract void Process(APDU apdu)//JCRE调用这个方法通知当前选择的applet另一个(或同一个)applet将被选择。
Public void deselect()//索取APDU buffer
public void process(APDU apdu){ byte[] apdu_buffer = apdu.getBuffer();}//设置JCRE为数据接受模式,返回它所读入的字节数,如果无数据,则返回0
public short setIncomingAndReceive()throws APDUExcetion;//数据读示例
public void process(APDU apdu){ byte[] apdu_buffer = =apdu.getbuffer(); short total_bytes = (short)(apdu_buffer[ISO7816.OFFSET_LC] & 0xFF);//读数据至APDU buffer
short read_count = apdu.setIncomingAndReceive();//获得剩余字节数
short bytes_left = (short)(total_bytes – read_count);while(true){
//处理APDU Buffer中的数据或者将数据拷贝到内部buffer
……//检查是否还有剩余数据,如果无,跳出循环。
If (bytes_left <=0) break; //如果有剩余数据,在读数据。 Read_count = apdu.receiveBytes((short)0);Bytes_left -= read_count;
}
//执行其它任务和向host送回响应 ……}//重新设置数据传送方向为输出,置JCRE为数据发送模式.剩余的输入数据将被丢弃,并且applet就不能再继续接收命令数据
Public short setOutgoing() throws APDUException;//调用了setOutgoing方法之后,applet必须调用setOutgoingLength方法,以向host指出它将实际发送总共多少响应数据字节(不包括SW)
public void setOutgoingLength(short length) throws APDUException;//sendBytes方法从APDU Buffer中指定位移bOff处发送len个数据字节.因此,applet在调用这个方法之前,必须在APDU Buffer中生成响应数据或从别处拷贝过来。
public void sendBytes(short bOff,short len) throws APDUException;//示例
public void process(APDU apdu){ //接收和处理命令APDU …… //现在准备好发送响应数据 //首先设置JCRE为数据发送模式并获得期望的行应数据长度(Le) short le = apdu.setOutgoing(); //接着通知host:applet将实际发送10个字节 apdu.setOugoingLength((short)10); //在APDU Buffer中准备数据,从位移0开始 …… //准备结束时,发送数据 apdu.sendBytes((short)0,(short)10);}//设置传输模式为发送,设置响应数据长度为len,从APDU Buffer 位移bOff起发送响应数据字节
public void setOutgoingAndSend(short bOff,short len) throws APDUException;//sendBytesLong方法从字节数组outDATA中的位移bOff开始处发送len字节数据.仅当已经先调用了setOutgoing和setOutgoingLength方法之后,它才能被调用。
public void sendBytesLong(byte[] outDATA,short bOff,short len) throws APDUException;//示例
//Get_Account_Info命令APDU要求applet发送账号拥有者的名字、账号,和截止日期。//另外,要求applet发送由名字、账号,和截止日期计算的hash值,以确保数据正确传输。//applet将账号持有者的名字、账号,和截止日期存储在独立的字节数组中。Private byte[] name; //20字节
Private byte[] account_number; //9字节Private byte[] expiration+date; //4字节//在处理了命令APDU后,applet现在准备好发送响应数据。
//响应数据中的字节数为://total_bytes = 20(name)+9(account_number)+4(expiration_date)+8(hash值)=41字节short total_bytes = (short)41;
//step1:
//设置数据传输方向为输出short le = apdu.setOutgoing;//step2://通知host响应中的实际字节数apdu.setOutgongLength(nametotaal_bytes);//step3://发送nameapdu.sendBytesLong(name,(short)0, (short)name.length);//发送账号apdu.sendBytesLong(account_number,(short)0, (short) account_number.length);//发送机制日期apdu.sendBytesLong(expiration_date,(short)0, (short) expiration_date.length);//现在,在APDU Buffer中计算shah值,//假定于位移0处生成hash值//……//发送shah值apdu.sendBytes((short)0,HASH_VALUE_LENGTH);//现在返回return;}