Skip to Main Content

Java Card

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Sample Smartcardio (Host side) applet interation application

796229Jun 17 2009 — edited Jul 1 2009
Hi All,

After nine months of researching and developing a java card applet and terminal side interface for my final year university project I was frustrated with the lack of sample code and tutorials available online.

My applet is aimed at students as an id card containing a student id, all the features of an electronic wallet, loyalty point system protected by a pin number. Pin is changeable. And can be found in this forum under the heading “Sample Javacard 2.2.1 Electronic wallet, Loyalty Points & StudentID applet”

The terminal interaction or host side application that communicates with this applet

As I have no finished my project I would like to share it with anyone that would like to see it.

While I would love to write a tutorial I simply do not have the time however below is the host side application I used in my project to interact with my applet, I hope for anyone that has read through java sun's tutorials this will be a help:

package terminal;


import javax.smartcardio.*;

import java.awt.HeadlessException;
import javax.swing.JOptionPane;
import java.util.List;
import java.text.DecimalFormat;


/**
 * @author Raymond Garrett
 *DT 354-4
 */

public class TerminalInteraction {
	//PackageID = |College    -   Hex: 																43 6f 6c 6c 65 67 65 41  70 70
	// AppletID = |CollegeApp
	//the select part of the select apdu is (00 A4 04 00) +(AID leght) + AID(.....) 
	private static byte[] SELECT = {(byte) 0x00, (byte) 0xA4, (byte) 0x04, (byte) 0x00, (byte) 0x0A, (byte)0x43, (byte)0x6f, (byte)0x6c, (byte)0x6c, (byte)0x65, (byte)0x67, (byte)0x65, (byte)0x41, (byte)0x70, (byte)0x70 };
	final static byte ACCOUNT_CLA = (byte)0xA0;
	final static byte VERIFY_PIN_INS = (byte)0x20;
	final static byte ADD_CREDIT_INS = (byte) 0x30;
	final static byte DEBIT_ACCOUNT_INS = (byte) 0x40;
	final static byte UPDATE_PIN_INS = (byte) 0x60;
	final static byte P1 = (byte) 0x00;
	final static byte P2 = (byte) 0x00;

	private static byte[] GET_BALANCE_CLA_INS = {(byte)0xA0,(byte) 0x50, (byte) 0x00, (byte) 0x00};
	private static byte[] ADMIN_RESET_CLA_INS = {(byte)0xA0,(byte) 0x70, (byte) 0x00, (byte) 0x00};
	private static byte[] PIN_TRIES_REMAINING_CLA_INS = {(byte)0xA0,(byte) 0x80, (byte) 0x00, (byte) 0x00};
	private static byte[] STUDENT_NUMBER_CLA_INS = {(byte)0xA0,(byte) 0x90, (byte) 0x00, (byte) 0x00};
	private static byte[] GET_LOYALTYPOINTS_CLA_INS = {(byte)0xA0,(byte) 0x45, (byte) 0x00, (byte) 0x00};
	private static byte[] CREDIT_LOYALTYPOINTS_CLA_INS = {(byte)0xA0,(byte) 0x47, (byte) 0x00, (byte) 0x00};
	


	private static CommandAPDU SELECT_APDU = new CommandAPDU(SELECT);
	private static CommandAPDU ADMIN_RESET_APDU = new CommandAPDU(ADMIN_RESET_CLA_INS);
	private static CommandAPDU GET_BALANCE_APDU = new CommandAPDU(GET_BALANCE_CLA_INS);
	private static CommandAPDU STUDENT_NUMBER_APDU = new CommandAPDU(STUDENT_NUMBER_CLA_INS);
	private static CommandAPDU PIN_TRIES_REMAINING_APDU = new CommandAPDU(PIN_TRIES_REMAINING_CLA_INS);
	
	private static CommandAPDU GET_LOYALTYPOINTS_BALANCE_APDU = new CommandAPDU(GET_LOYALTYPOINTS_CLA_INS);
	private static CommandAPDU CREDIT_LOYALTYPOINTS_APDU = new CommandAPDU(CREDIT_LOYALTYPOINTS_CLA_INS);
	
	private static CommandAPDU VERIFY_PIN_APDU; // Command created in verifyPin method.
	private static CommandAPDU ADD_CREDIT_APDU;  // Command created in AddCredit method.
	private static CommandAPDU DEBIT_ACCOUT_APDU;  // Command created in debitAccount method.
	private static CommandAPDU UPDATE_PIN_APDU;	// Command created in updatePin method.
	private ResponseAPDU responseAPDU = null;
	private TerminalFactory terminalFactory = null;
	private CardTerminals cardTerminals = null;
	private List<CardTerminal> cardTerminalsList = null;
	private Card card = null;
	private CardTerminal cardTerminal = null;
	private CardChannel cardChannel = null; 
	private AccountView myAccountView;
	private String studentID = null;
	private Thread cardPresentThread = null;
	private Thread waitForCardRemovalThread = null;
	final static short SW_NO_ERROR = (short) 0x9000;
	final static short SW_VERIFICATION_FAILED = 0x6300;
	final static short SW_PIN_VERIFICATION_REQUIRED = 0x6301;
	final static short SW_INVALID_TRANSACTION_AMOUNT = 0x6E83;
	final static short SW_EXCEED_MAXIMUM_BALANCE = 0x6E84;
	final static short SW_NEGATIVE_BALANCE = 0x6E85;
	final static short SW_PIN_TO_LONG = 0x6E86;
	final static short SW_PIN_TO_SHORT = 0x6E87;




	public TerminalInteraction(AccountView myAccountView) {
		this.myAccountView = myAccountView;
		initialise();
	}


	public void initialise() { 
		setTerminalFactory(getTerminalFactory());
		setCardTerminals(getTerminalFactory().terminals());
		try {
			setCardTerminalsList(getCardTerminalsList());
		} catch (Exception e) {
		}
		startTread();
	}

	private void startTread(){
		Runnable waitForCardRemoval = new Runnable() {
			
			public void run() {
				while (true) {
					try {
						Thread.sleep(1000);
						if(getCardTerminal().waitForCardAbsent(0)) {
							logout();
							//return;
						}
					} catch (CardException e) {
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		};
		
		setWaitForCardRemovalThread(new Thread(waitForCardRemoval));
	}




	public void startCommunication() {
		while (true) {
			try {
				for ( CardTerminal terminal : getCardTerminals().list(CardTerminals.State.CARD_INSERTION)){
					try {
						if(!getWaitForCardRemovalThread().isAlive()) {
							getWaitForCardRemovalThread().start();
						}
						else {
						}
						getMyAccountView().getCardNoticeLabel().setText("Card Inserted!");
						getMyAccountView().getInstructionLabel().setText("Please do not remove card!");
						getMyAccountView().getInstructionLabel().setVisible(true);
						getMyAccountView().getResultLabel().setText("Enter pin");
						getMyAccountView().getResultLabel().setVisible(true);
						getMyAccountView().getCancelPinUpdateButton().setVisible(false);
						//(*) connect to the card using any available protocol (instead of (T=1) which I started with)
						setCardTerminal(terminal);
						setCard(terminal.connect("*")); 	
					} catch (Exception e) {
						System.out.println("Terminal NOT connected: " + e.toString());
						logout();
					}
					getCard().getATR();
					setCardChannel(card.getBasicChannel());
					try {
						if (check9000(getCardChannel().transmit(SELECT_APDU))) {
							getMyAccountView().getPinContentPane1().setVisible(true);
							if (getStudentID() != "Error") {
								getMyAccountView().getDataLog().insertCardInsetTime(getStudentID());
							}
							else {
								JOptionPane.showMessageDialog(null, "Error\nStudent number not found in database\n " +
										"Please contact DIT Registrar", "ERROR NOTICE", JOptionPane.ABORT);
								logout();
							}
							
						}
						else {
							return;
						}
					} catch (CardException e) {
						e.printStackTrace();
						return;
					}
					return;
				}
			}
			catch (HeadlessException e) {
				e.printStackTrace();
			} catch (CardException e) {
				e.printStackTrace();
			}
		}
	}
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Jul 29 2009
Added on Jun 17 2009
14 comments
518 views