Smart Card Developer's Kit:The FlexCash Card: An E-commerce Smart Card Application
Previous
Table of Contents
Next
The Design of the FlexCash Smart Card Program
The Java program on the FlexCash card consists of five modules: a monitor, three e-purses, and the frequent buyer points purse. Figure 11.2 shows how three modules connect to each other. The monitor communicates with the outside world and passes messages to the other four applications. This general architecture lets Smart Commerce Solutions quickly create smart cards that are multiapplication combinations of existing single-application cards.
Figure 11.2. Modules on the FlexCash card.
Which application runs when the FlexCash card is activated depends on a flag stored in EEPROM called the application flag. If the application flag is 0, the FlexCash monitor application handles the interaction with the terminal. If the flag is some number k greater than 0, the monitor passes commands from the terminal to installed application k and sends the response generated by the application back to the terminal.
There is one special command that the monitor application handles no matter what the application flag is set to: SET APPLICATION FLAG. This lets the cardholder change from one application to another, regardless of what type of card the FlexCash card is currently acting as.
FlexCash Card Monitor Implementation
The FlexCash card monitor handles the following commands:
GET VALUES (E1 00 00 00 04)
DECREMENT LOYALTY by yy (E1 02 00 yy 00)
SET APPLICATION FLAG to xx (E1 04 00 xx 00)
The GET VALUES command returns the current values of the three purses and the loyalty points purse. It is used by the cardholder to find out how much value he or she has on his or her FlexCash card. The DECREMENT LOYALTY command subtracts a given value from the loyalty purse value. It is used to redeem loyalty purse points.
In passing commands from the terminal to one of the e-cash applications, the monitor recognizes the command for each application that represents spending money and increments the loyalty points purse corresponding to the amount of e-cash being deducted from the e-cash purse.
Listing 11.1 is the FlexCash monitor program, written in Java against the Java Card 1.0 API, which turns the general-purpose Cyberflex card into a FlexCash card. For the sake of clarity, this code assumes that all three purses have the same ATR, which would clearly not be the case if the cards really existed.
Listing 11.1. FlexCash code on the Java Card.
/*
** FlexCash Smart Card
*/
public class FlexCash {
static final byte MONITOR = (byte) 0;
static final byte ECOINS = (byte) 1;
static final byte EBUCKS = (byte) 2;
static final byte EMONEY = (byte) 3;
public static void main() {
byte [] Array, Value, Ack;
byte Application, Status;
Array = new byte[8];
// Send the first byte of the ATR
Array[0] = (byte)0x3B;
_OS.SendMessage(Array,(byte)0x01);
// Reset the card during debugging
//_OS.Execute((short)0,(byte)0);
// Read in the purse values and the application flag
_OS.SelectFile((short)0x7777);
_OS.SelectFile((short)0x7701);
Value = new byte[5];
_OS.ReadBinaryFile((short)0,(byte)5, Value);
Application = Value[4];
// Fill the last part of the FlexCash Card ATR and send it
if(Application == MONITOR) {
Array[0] = (byte)0x32; Array[1] = (byte)0x15;
Array[2] = (byte)0x00; Array[3] = (byte)0x49;
Array[4] = (byte)0x10;
_OS.SendMessage(Array,(byte)5);
}
/* Verify Key 0 */
Array[0]=(byte)0xAD; Array[1]=(byte)0x9F;
Array[2]=(byte)0x61; Array[3]=(byte)0xFE;
Array[4]=(byte)0xFA; Array[5]=(byte)0x20;
Array[6]=(byte)0xCE; Array[7]=(byte)0x63;
_OS.VerifyKey((byte)0, Array, (byte)8);
Ack = new byte[1];
while (true) {
// Wait for a 5-byte command
_OS.GetMessage(Array,(byte)0x05,(byte)0x00);
Ack[0] = Array[1];
// Trap the Set Application command
if((Array[0] == (byte)0xE1) && (Array[1] == (byte)0x04)) {
Value[4] = Ack[0] = Application = Array[3];
Status = _OS.WriteBinaryFile((short)4, (byte)1, Ack);
_OS.SendStatus(Status);
continue;
}
// Pass the command to the active application
switch(Application) {
case MONITOR:
if(Array[0] == (byte)0xE1) {
if (Array[1] == (byte)0x02) { // Decrement Loyalty
Value[0] = (byte)(Value[0]-Array[3]);
Status =
_OS.WriteBinaryFile((short)0,(byte)1, Value);
_OS.SendStatus(Status);
continue;
}
if(Array[1] == (byte)0x00) { // Get Values
_OS.SendMessage(Ack, (byte)1);
_OS.SendMessage(Value, (byte)4);
_OS.SendStatus((byte)0x00);
continue;
}
} else { // Unknown Monitor command
_OS.Execute((short)0,(byte)0);
_OS.SendStatus((byte)0x90);
}
case ECOINS:
// _OS.ECoins(Array);
Value[1] = Ack[0] = (byte)(Value[1]-Array[3]);
Status = _OS.WriteBinaryFile((short)1,(byte)1, Ack);
_OS.SendStatus(Status);
break;
case EBUCKS:
// _OS.EBucks(Array);
Value[2] = Ack[0] = (byte)(Value[2]-Array[3]);
Status = _OS.WriteBinaryFile((short)2,(byte)1, Ack);
_OS.SendStatus(Status);
break;
case EMONEY:
// _OS.EMoney(Array);
Value[3] = Ack[0] = (byte)(Value[3]-Array[3]);
Status = _OS.WriteBinaryFile((short)3,(byte)1, Ack);
_OS.SendStatus(Status);
break;
default:
_OS.SendStatus((byte)0x90);
break;
} // end of switch
} // end of while
} // end of main
} // end of class
Previous
Table of Contents
Next