package purseclientjc;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.Scanner;
import javax.print.attribute.standard.MediaSize.ISO;
import javax.sound.midi.SysexMessage;
import com.sun.javacard.apduio.Apdu;
import com.sun.javacard.apduio.CadT1Client;
import com.sun.javacard.apduio.CadTransportException;
/**
*
*
*
* @author C Michoudet, A Vernotte
*
*/
public class PurseClientJC {
//Applet CLA & INSs
private static final byte CLA_PURSEAPPLET = (byte) 0x25;
public static final byte INS_VERIFY = 0x01;
public static final byte INS_CREDIT = 0x02;
public static final byte INS_DEBIT = 0x03;
public static final byte INS_GET_BALANCE = 0x04;
private static final byte INS_GET_STATE = 0x05;
private static final byte INS_CONFIGURE = 0x06;
// LifeCycleState
public static final byte LFC_PRE_PERSO = (byte) 0x50;
public static final byte LFC_USE = (byte) 0x51;
public static final byte LFC_INVALID = (byte) 0x52;
public static final byte LFC_DEAD = (byte) 0x53;
/**
* @param args
* @throws IOException
* @throws CadTransportException
*/
// connection
private CadT1Client cad;
private Socket sckCarte;
Apdu apdu;
/**
* M�thode permettant d'envoyer une commande APDU
*
* @param ins le type d'instruction
* @param P1 parametre 1
* @param P2 parametre 2
* @param lc taille donnees
* @param data donnees
* @param le taille retour
* @throws IOException
* @throws CadTransportException
*/
private void send(byte ins, byte P1, byte P2, byte lc, byte[] data, byte le)
throws IOException, CadTransportException {
apdu = new Apdu();
apdu.command[Apdu.CLA] = CLA_PURSEAPPLET;
apdu.command[Apdu.INS] = ins;
apdu.command[Apdu.P1] = P1;
apdu.command[Apdu.P2] = P2;
apdu.setLc(lc);
apdu.setLe(le);
apdu.setDataIn(data);
cad.exchangeApdu(apdu);
}
/**
* Une fois connect� � la carte, que la commande powerUP a �t� envoy�e et
* que la carte est selectionn�e, on peut passer au traitement.
*
* C'est le menu principal.
* @throws CadTransportException
* @throws IOException
*/
public void exec() throws CadTransportException, IOException {
Scanner sc = new Scanner(System.in);
String get;
byte[] val;
/* On verifie l'etat actuel de la carte */
send(PurseClientJC.INS_GET_STATE,(byte)0x00,(byte)0x00,(byte)0x00,new byte[]{},(byte)0x00);
if (apdu.getStatus() != 0x9000) {
System.err.println("Erreur Fatale");
return;
}
/* Personnalisation Carte */
if (apdu.dataOut[0] == PurseClientJC.LFC_PRE_PERSO) {
System.out.println();
System.out.println("Application cliente Javacard");
System.out.println("-------- CONFIG ------------");
System.out.println();
System.out.print("Code Pin User : ");
get = sc.next();
byte[] recpin = new byte[8];
for(int i = 0 ; i<4 ; i++) {
recpin[i] = (byte) (get.getBytes()[i] - 48);
}
System.out.print("Code Pin Bank : ");
get = sc.next();
for(int i = 4 ; i<8 ; i++) {
recpin[i] = (byte) (get.getBytes()[i-4] - 48);
}
send(PurseClientJC.INS_CONFIGURE,(byte)0x00,(byte)0x00,(byte)0x08,recpin,(byte)0x00);
}
if (apdu.getStatus() == 0x6700) {
System.err.println("Les mots de passe doivent �tre de taille 4.");
} else if (apdu.getStatus() != 0x9000) {
System.err.println("Erreur Dans la configuration ->"+apdu.getStatus());
return;
} else {
System.out.println("CONFIG OK");
}
if (apdu.getStatus() != 0x9000) {
System.err.println("Erreur Fatale");
return;
}
/* Menu principal */
boolean fin = false;
while (!fin) {
send(PurseClientJC.INS_GET_STATE,(byte)0x00,(byte)0x00,(byte)0x00,new byte[]{},(byte)0x00);
if (apdu.dataOut[0] == PurseClientJC.LFC_DEAD) {
System.err.println("CARTE MORTE");
return;
}
if (apdu.dataOut[0] == PurseClientJC.LFC_INVALID){
System.err.println("CARTE BLOQUEE - Contacter votre banque.");
return;
}
if (apdu.dataOut[0] == PurseClientJC.LFC_USE) {
System.out.println();
System.out.println("Application cliente Javacard");
System.out.println("----------------------------");
System.out.println();
System.out.println("1 - Interroger la Banque");
System.out.println("2 - Credit");
System.out.println("3 - Debit");
System.out.println("4 - Quitter");
System.out.println();
System.out.println("Votre choix ?");
int choix = System.in.read();
while (!(choix >= '1' && choix <= '4')) {
choix = System.in.read();
}
apdu = new Apdu();
apdu.command[Apdu.CLA] = PurseClientJC.CLA_PURSEAPPLET;
apdu.command[Apdu.P1] = 0x00;
apdu.command[Apdu.P2] = 0x00;
switch (choix) {
case '1':
/* Le client verifie le solde */
send(PurseClientJC.INS_GET_BALANCE,(byte)0x00,(byte)0x00,(byte)0x00,new byte[]{},(byte)0x00);
if (apdu.getStatus() != 0x9000) {
System.err.println("Une erreur est survenue");
} else {
System.out.println("Solde : " + apdu.dataOut[1]);
}
break;
case '2':
/* Le client veut cr�diter la carte :
* D'abord, on v�rifie s'il a d�j� renseign� son code pin (si ce n'est pas le cas, il devra le donner)
* ensuite on cr�dite l'argent
*/
System.out.print("Valeur : ");
val = new byte[]{sc.nextByte()};
send(PurseClientJC.INS_CREDIT,(byte)0x00,(byte)0x00,(byte)0x01,val,(byte)0x00);
if (apdu.getStatus() == 0x6301) {
// Code pin pas renseign�
System.out.print("Code Pin : ");
get = sc.next();
if (get.length() != 4) {
System.err.println("Code Pin invalide");
break;
}
byte[] recpin = new byte[4];
for(int i = 0 ; i<recpin.length ; i++) {
recpin[i] = (byte) (get.getBytes()[i] - 48);
}
send(PurseClientJC.INS_VERIFY,(byte)0x00,(byte)0x00,(byte)0x04,recpin,(byte)0x00);
if (apdu.getStatus() == 0x9000) {
send(PurseClientJC.INS_CREDIT,(byte)0x00,(byte)0x00,(byte)0x01,val,(byte)0x00);
if (apdu.getStatus() == 0x9000) {
System.out.println("OK");
} else {
System.err.println("ERROR -> "+apdu.getStatus());
}
} else {
System.err.println(apdu.getStatus()+" --> BAD PIN");
}
} else if (apdu.getStatus() == 0x9000) {
System.out.println("OK");
} else {
System.err.println("MONTANT INVALIDE");
}
break;
case '3':
apdu.command[Apdu.INS] = PurseClientJC.INS_DEBIT;
System.out.print("Valeur : ");
apdu.setLc(1);
apdu.setDataIn(new byte[]{sc.nextByte()});
cad.exchangeApdu(apdu);
if (apdu.getStatus() != 0x9000) {
System.out.println("Erreur : status word different de 0x9000 -> "+apdu.getStatus());
} else {
System.out.println("OK");
}
break;
case '4':
fin = true;
break;
}
}
}
}
private void connect() {
try {
sckCarte = new Socket("localhost", 9025);
sckCarte.setTcpNoDelay(true);
BufferedInputStream input = new BufferedInputStream(sckCarte.getInputStream());
BufferedOutputStream output = new BufferedOutputStream(sckCarte.getOutputStream());
cad = new CadT1Client(input, output);
} catch (Exception e) {
System.out.println("Erreur : impossible de se connecter a la Javacard");
return;
}
}
private void select() {
apdu = new Apdu();
apdu.command[Apdu.CLA] = 0x00;
apdu.command[Apdu.INS] = (byte) 0xA4;
apdu.command[Apdu.P1] = 0x04;
apdu.command[Apdu.P2] = 0x00;
byte[] appletAID = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x00 };
apdu.setDataIn(appletAID);
try {
cad.exchangeApdu(apdu);
} catch (IOException e) {
e.printStackTrace();
} catch (CadTransportException e) {
e.printStackTrace();
}
if (apdu.getStatus() != 0x9000) {
System.out.println("Erreur lors de la s�lection de l'applet -> "+apdu.getStatus());
System.exit(1);
}
}
private void powerDown() {
/* Mise hors tension de la carte */
try {
cad.powerDown();
} catch (Exception e) {
System.out.println("Erreur lors de l'envoi de la commande Powerdown");
return;
}
}
private void powerUp() {
/* Mise en tension de la carte */
try {
cad.powerUp();
} catch (Exception e) {
System.out.println("Erreur lors de l'envoi de la commande PowerUp");
return;
}
}
public static void main(String[] args) throws IOException, CadTransportException {
PurseClientJC pc = new PurseClientJC();
pc.connect();
pc.powerUp();
pc.select();
pc.exec();
pc.powerDown();
}
}