📄 javapursecrypto.java
字号:
/* * Copyright ? 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. *//* * @(#)JavaPurseCrypto.java 1.4 03/06/06 */package com.sun.javacard.samples.JavaPurseCrypto;import javacard.framework.*;import javacard.security.*;//import javacardx.crypto.*;import com.sun.javacard.samples.SampleLibrary.JavaLoyaltyInterface;/** * This class is intended to demonstrate how an electronic cash application * might be developed using Java Card * <p>See <em>Java Card(TM) Reference Implementation User's Guide</em> * for details. * * @author Vadim Temkin, Modified to include cryptographic signatures by M. Saltz */public class JavaPurseCrypto extends Applet { /* * * Constants * */ final static byte PURSE_CLA = (byte)0x80; //CLA value for Java Purse final static byte VERIFY = (byte)0x20; //INS value for ISO 7816-4 VERIFY command final static byte READ = (byte)0xB2; //INS value for ISO 7816-4 READ RECORD command final static byte INITIALIZE_TRANSACTION = (byte)0x20; //INS byte for Initialize Transaction final static byte COMPLETE_TRANSACTION = (byte)0x22; //INS byte for Complete Transaction final static byte INITIALIZE_UPDATE = (byte)0x24; //INS byte for Initialize Parameter Update final static byte COMPLETE_UPDATE = (byte)0x26; //INS byte for Complete Parameter Update final static byte CREDIT = (byte)0x01; //P1 byte for Credit in Initialize Transaction final static byte DEBIT = (byte)0x02; //P1 byte for Debit in Initialize Transaction final static byte MASTER_PIN = (byte)0x81; //P2 byte for Master PIN in Verify final static byte USER_PIN = (byte)0x82; //P2 byte for User PIN in Verify final static short MAX_MAC_DATA = (short) 0x001E; //maximimum length of data used in MAC final static short SW_CREDIT_TOO_HIGH = (short)0x9101;//SW bytes for Credit Too High condition final static short SW_NOT_ENOUGH_FUNDS = (short)0x9102;//SW bytes for Not Enough Funds condition final static short SW_AMOUNT_TOO_HIGH = (short)0x9103;//SW bytes for Amount Too High condition final static short SW_COMMAND_OUT_OF_SEQUENCE = (short)0x9104;//SW bytes for Command out of Sequence final static short SW_WRONG_SIGNATURE = (short)0x9105;//SW bytes for Wrong Signature condition final static short SW_PIN_FAILED = (short)0x69C0;//SW bytes for PIN Failed condition final static short SW_SUCCESS = (short)0x9000;//SW bytes for success, used in MAC. //The last nibble is replaced with the //number of remaining tries final static byte LC_IT = 10; //Lc byte for Initialize Transaction final static byte LC_CT = 13; //Lc byte for Complete Transaction final static byte LC_CU_MIN = 18; //Lc byte for Complete Update final static byte CAD_ID_OFFSET = 7; //Offset for CAD ID in Process Initialize Transaction final static short DATE_LENGTH = 3; //Length of ExpDate array final static short DATETIME_LENGTH = 5;//Length of DateTime array final static short ID_LENGTH = 4; //Length for CAD ID and Purse ID arrays final static short SHORT_LENGTH= 2; //Length of a short value for offset computations final static short START = 0; //For offset computations final static short SIGNATURE_LENGTH = 8; //Length of signatures final static short MAX_LOYALTY = 4; //Max number of loyalty applets // transientShorts array indices final static byte TN_IX = 0; final static byte NEW_BALANCE_IX=(byte)TN_IX+1; final static byte CURRENT_BALANCE_IX=(byte)NEW_BALANCE_IX+1; final static byte AMOUNT_IX=(byte)CURRENT_BALANCE_IX+1; final static byte TRANSACTION_TYPE_IX=(byte)AMOUNT_IX+1; final static byte SELECTED_FILE_IX=(byte)TRANSACTION_TYPE_IX+1; final static byte NUM_TRANSIENT_SHORTS=(byte)SELECTED_FILE_IX+1; // transientBools array indices final static byte TRANSACTION_INITIALIZED=0; final static byte UPDATE_INITIALIZED=(byte)TRANSACTION_INITIALIZED+1; final static byte NUM_TRANSIENT_BOOLS=(byte)UPDATE_INITIALIZED+1; // constants for response to applet SELECT command private final static byte FCI_TEMPLATE_TAG = (byte)0x6F; private final static byte FCI_AID_TAG = (byte)0x84; private static byte[] FCI_PROPERIETARY = {(byte)0xA5, // tag (byte)0x01, // length (byte)0x42 }; // value private ParametersFile parametersFile; private CyclicFile transactionLogFile; private short TN; private short PUN; private boolean isPersonalized; //set to true when Master PIN is updated first time /* * File System emulation constants */ final static short PARAMETERS_FID = (short) 0x9102; final static short TRANSACTION_LOG_FID = (short) 0x9103; final static short BALANCES_FID = (short) 0x9104; final static byte FID_BYTE = (byte) 0x91; final static byte TRANSACTION_RECORD_LENGTH = 18; final static byte TRANSACTION_RECORD_NUMBER = 10; final static byte BALANCES_RECORD_LENGTH = 6; final static byte BALANCES_RECORD_NUMBER = 1; final static byte PARAMETERS_RECORD_NUMBER = 11; final static byte OFFSET_BAL_CURRENT = 0; final static byte OFFSET_BAL_MAX = 2; final static byte OFFSET_AMOUNT_MAX = 4; final static byte NUMBER_OF_FILES = 3; private OwnerPIN masterPIN; private OwnerPIN userPIN; /* * Tags for TLV records in Complete Parameter Update C-APDU. */ final static byte MASTER_PIN_UPDATE = (byte)0xC1; final static byte USER_PIN_UPDATE = (byte)0xC2; final static byte EXP_DATE_UPDATE = (byte)0xC5; final static byte PURSE_ID_UPDATE = (byte)0xC6; final static byte MAX_BAL_UPDATE = (byte)0xC7; final static byte MAX_M_UPDATE = (byte)0xC8; final static byte VERSION_UPDATE = (byte)0xC9; final static byte LOYALTY1_UPDATE = (byte)0xCA; final static byte LOYALTY2_UPDATE = (byte)0xCB; final static byte LOYALTY3_UPDATE = (byte)0xCC; final static byte LOYALTY4_UPDATE = (byte)0xCD; final static short TLV_OFFSET = 13; //Offset of TLV in Complete Parameter Update /* * The DES key used for DES MAC calculations. The keyData should be gotten via an update * method call in a real application. */ byte[] keyData = {(byte)0x11, (byte)0x33, (byte)0x22, (byte)0x05, (byte)0x44, (byte)0x77, (byte)0x06, (byte)0x08}; /* * * Various and sundry byte arrays * */ private byte[] CAD_ID_array; private byte[] byteArray8; // Signature work array private short[] transientShorts; private boolean[] transientBools; private byte[] ID_Purse; private byte[] ExpDate; private byte[] balancesRecord; private byte[] MAC_buffer; /* * The two associated arrays to represent Loyalty Applets. * If value of loyaltyCAD matches first 2 bytes of CAD ID for transaction * the grantPoints method of corresponding loyalty Shareable Interface Object * is called. These arrays are populated by Parameter Update APDU commands. */ private short[] loyaltyCAD; private JavaLoyaltyInterface[] loyaltySIO; /* * signature/key objects */ private DESKey deskey; private Signature sig; /** * Installs Java Purse applet. * @param bArray install parameter array. * @param bOffset where install data begins. * @param bLength install parameter data length. */ public static void install( byte[] bArray, short bOffset, byte bLength ) { new JavaPurseCrypto(bArray, bOffset, bLength); } /** * Performs memory allocations, initialization, and applet registration. * * @param bArray received by install. * @param bOffset received by install. * @param bLength received by install. */ protected JavaPurseCrypto(byte[] bArray, short bOffset, byte bLength) { ID_Purse = new byte[ID_LENGTH]; ExpDate = new byte[DATE_LENGTH]; ExpDate[0] = (byte)12; ExpDate[1] = (byte)31; ExpDate[2] = (byte)99; balancesRecord = new byte[BALANCES_RECORD_LENGTH]; loyaltyCAD = new short[MAX_LOYALTY]; loyaltySIO = new JavaLoyaltyInterface[MAX_LOYALTY]; TN = 0; PUN = 0; isPersonalized = false; //Create transient objects. transientShorts = JCSystem.makeTransientShortArray( NUM_TRANSIENT_SHORTS, JCSystem.CLEAR_ON_DESELECT); transientBools = JCSystem.makeTransientBooleanArray( NUM_TRANSIENT_BOOLS, JCSystem.CLEAR_ON_DESELECT); CAD_ID_array = JCSystem.makeTransientByteArray( (short)4, JCSystem.CLEAR_ON_DESELECT); // initialize crypto key/signature objects and work array. byteArray8 = JCSystem.makeTransientByteArray( (short)8, JCSystem.CLEAR_ON_DESELECT); deskey = (DESKey)KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES, false); MAC_buffer = JCSystem.makeTransientByteArray( MAX_MAC_DATA, JCSystem.CLEAR_ON_DESELECT); deskey.setKey(keyData, (short)0); sig = Signature.getInstance(Signature.ALG_DES_MAC8_ISO9797_M2, false); masterPIN = new OwnerPIN ((byte)1, (byte)8); //There is only one try - it's not supposed to be done by human operator userPIN = new OwnerPIN ((byte)5, (byte)8); parametersFile = new ParametersFile(PARAMETERS_RECORD_NUMBER); transactionLogFile = new CyclicFile(TRANSACTION_RECORD_NUMBER, TRANSACTION_RECORD_LENGTH); Util.setShort(balancesRecord, OFFSET_BAL_CURRENT, (short)0); /* * if AID length is not zero register Java Loyalty * applet with specified AID * * NOTE: all the memory allocations should be performed before register() */ byte aidLen = bArray[bOffset]; if (aidLen== (byte)0){ register(); } else { register(bArray, (short)(bOffset+1), aidLen); } } /** * Performs the session finalization. */ public void deselect() { userPIN.reset(); masterPIN.reset(); } /** * Dispatches APDU commands. * @param apdu APDU object */ public void process(APDU apdu) { byte[] buffer = apdu.getBuffer(); // Mask channel info out buffer[ISO7816.OFFSET_CLA] = (byte)(buffer[ISO7816.OFFSET_CLA] & (byte)0xFC); if (buffer[ISO7816.OFFSET_CLA] == PURSE_CLA) { switch (buffer[ISO7816.OFFSET_INS]) { case INITIALIZE_TRANSACTION: processInitializeTransaction(apdu); break; case COMPLETE_TRANSACTION: processCompleteTransaction(apdu); break; case INITIALIZE_UPDATE: processInitializeUpdate(apdu); break; case COMPLETE_UPDATE: processCompleteUpdate(apdu); break; default: ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); } } else if (buffer[ISO7816.OFFSET_CLA] == ISO7816.CLA_ISO7816) { if (buffer[ISO7816.OFFSET_INS] == VERIFY){ processVerifyPIN(apdu); } else if (buffer[ISO7816.OFFSET_INS] == ISO7816.INS_SELECT){ if (selectingApplet()) processSelectPurse(apdu); else processSelectFile(apdu); } else if (buffer[ISO7816.OFFSET_INS] == READ) { processReadRecord(apdu); } else ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); } else ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED); } /** * Handles Select Purse APDU. * @param apdu APDU object */ private void processSelectPurse(APDU apdu) { // // There might be multiple instances of Java Purse on the card with // different AID values. This method returns the FCI here identifying its // particular instance. // // Format of response data // FCI tag, FCI length, // AID tag, length, value, // PROPRIETARY tag, value. // // TEMPLATE byte[] buffer = apdu.getBuffer(); buffer[0] = FCI_TEMPLATE_TAG; // buffer[1] set later
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -