2016-05-01 5 views
0

Ich bin ein Neuling in der Welt von javacard. Ich habe ein Brieftaschen-Applet, das erfolgreich in Netbeans läuft (ich kann Kredit-, Debit-, Check-Balance-, Verifizierungs-Pin usw. mit APDUs in der Gerätekonsole). Ich bin beauftragt, eine Host-Anwendung zu schreiben, um mit dieser Karte in Netbeans zu kommunizieren, ohne die Smartcard-Konsole zu verwenden. Nach ein wenig Nachforschungen muss ich die Klasse javax.smartcardio in meine Host-Anwendung importieren. Wie Sie jedoch wissen, gibt es dazu nur wenig Dokumentation. Für viele von uns, die es schwer haben, in diese Welt der Smartcard-Programmierung einzutauchen, wird jede Hilfe geschätzt und hilfreich sein. Unten ist mein Applet-Code. Pin wurde über Parameter wie 1122334455667788 über Projekteigenschaften übergeben.Wie kann eine Host-Anwendung ein Javacard-Applet auf einer simulierten Smartcard in Netbeans abfragen?

package classicapplet1; 

//package com.sun.javacard.samples.wallet; 

import javacard.framework.*; 

    public class Wallet extends Applet { 

    // codes of CLA byte in the command APDUs 

    final static byte Wallet_CLA = (byte) 0xB0; 

    // codes of INS byte in the command APDUs 

    final static byte VERIFY = (byte) 0x20; 

    final static byte CREDIT = (byte) 0x30; 

    final static byte DEBIT = (byte) 0x40; 

    final static byte GET_BALANCE = (byte) 0x50; 

    // maximum wallet balance 

    final static short MAX_BALANCE = 10000; 

    // maximum transaction amount 

    final static byte MAX_TRANSACTION_AMOUNT = 100; 

    // maximum number of incorrect tries before the 

    // PIN is blocked 

    final static byte PIN_TRY_LIMIT = (byte) 0x03; 

    // maximum size PIN 

    final static byte MAX_PIN_SIZE = (byte) 0x08; 

    // Applet-specific status words: 

    final static short SW_VERIFICATION_FAILED = 0x6300; 

    final static short SW_PIN_VERIFICATION_REQUIRED = 0x6301; 

    final static short SW_INVALID_TRANSACTION_AMOUNT = 0x6A83; 

    final static short SW_EXCEED_MAXIMUM_BALANCE = 0x6A84; 

    final static short SW_NEGATIVE_BALANCE = 0x6A85; 

    // instance variables declaration 

    OwnerPIN pin; 

    short balance; 

    /** 
    * 
    * called by the JCRE to create an applet instance 
    */ 

    public static void install(byte[] bArray, short bOffset, byte bLength) { 

     // create a Wallet applet instance 

     new Wallet(bArray, bOffset, bLength); 

    } // end of install method 

    /** 
    * 
    * private constructor — called by the install method to 
    * 
    * instantiate a Wallet instance 
    */ 


    private Wallet(byte[] bArray, short bOffset, byte bLength) { 

     pin = new OwnerPIN(PIN_TRY_LIMIT, MAX_PIN_SIZE); 

     // bArray contains the PIN initialization value 

     pin.update(bArray, bOffset, bLength); 

     // register the applet instance with the JCRE 

     register(); 

    } // end of the constructor 

    /** 
    * 
    * initialize the applet when it is selected 
    */ 

    public boolean select() { 

     // the applet declines to be selected 

     // if the pin is blocked 

     if (pin.getTriesRemaining() == 0) 

      return false; 

     return true; 

    } // end of select method 

    /** 
    * 
    * perform any cleanup and bookkeeping tasks before 
    * 
    * the applet is deselected 
    */ 

    public void deselect() { 

     // reset the pin 

     pin.reset(); 

    } 

    /** 
    * 
    * process APDUs 
    */ 

    public void process(APDU apdu) { 

     // APDU object carries a byte array (buffer) to 

     // transfer incoming and outgoing APDU header 

     // and data bytes between the card and the host 

     // at this point, only the first five bytes 

     // [CLA, INS, P1, P2, P3] are available in 

     // the APDU buffer 

     byte[] buffer = apdu.getBuffer(); 

     // return if the APDU is the applet SELECT command 

     if (selectingApplet()) 

      return; 

     // verify the CLA byte 

     if (buffer[ISO7816.OFFSET_CLA] != Wallet_CLA) 

      ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED); 

     // check the INS byte to decide which service method to call 

     switch (buffer[ISO7816.OFFSET_INS]) { 

     case GET_BALANCE: 
      getBalance(apdu); 
      return; 

     case DEBIT: 
      debit(apdu); 
      return; 

     case CREDIT: 
      credit(apdu); 
      return; 

     case VERIFY: 
      verify(apdu); 
      return; 

     default: 
      ISOException.throwIt 

      (ISO7816.SW_INS_NOT_SUPPORTED); 

     } 

    } // end of process method 

    /** 
    * 
    * add money to the wallet 
    */ 

    private void credit(APDU apdu) { 

     // verify authentication 

     if (!pin.isValidated()) 

      ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED); 

     byte[] buffer = apdu.getBuffer(); 

     // get the number of bytes in the 

     // data field of the command APDU 

     byte numBytes = buffer[ISO7816.OFFSET_LC]; 

     // recieve data 

     // data are read into the apdu buffer 

     // at the offset ISO7816.OFFSET_CDATA 

     byte byteRead = (byte) (apdu.setIncomingAndReceive()); 

     // error if the number of data bytes 

     // read does not match the number in the Lc byte 

     if ((numBytes != 1) || (byteRead != 1)) 

      ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); 

     // get the credit amount 

     byte creditAmount = buffer[ISO7816.OFFSET_CDATA]; 

     // check the credit amount 

     if ((creditAmount > MAX_TRANSACTION_AMOUNT) 

     || (creditAmount < 0)) 

      ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT); 

     // check the new balance 

     if ((short) (balance + creditAmount) > MAX_BALANCE) 

      ISOException.throwIt(SW_EXCEED_MAXIMUM_BALANCE); 

     // credit the amount 

     balance = (short) (balance + creditAmount); 

     return; 

    } // end of deposit method 

    /** 
    * 
    * withdraw money from the wallet 
    */ 

    private void debit(APDU apdu) { 

     // verify authentication 

     if (!pin.isValidated()) 

      ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED); 

     byte[] buffer = apdu.getBuffer(); 

     byte numBytes = (byte) (buffer[ISO7816.OFFSET_LC]); 

     byte byteRead = (byte) (apdu.setIncomingAndReceive()); 

     if ((numBytes != 1) || (byteRead != 1)) 

      ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); 

     // get debit amount 

     byte debitAmount = buffer[ISO7816.OFFSET_CDATA]; 

     // check debit amount 

     if ((debitAmount > MAX_TRANSACTION_AMOUNT) 

     || (debitAmount < 0)) 

      ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT); 

     // check the new balance 

     if ((short) (balance - debitAmount) < (short) 0) 

      ISOException.throwIt(SW_NEGATIVE_BALANCE); 

     balance = (short) (balance - debitAmount); 

    } // end of debit method 

    /** 
    * 
    * the method returns the wallet’s balance 
    */ 

    private void getBalance(APDU apdu) { 

     byte[] buffer = apdu.getBuffer(); 

     // for(short i=0;i<buffer.length;i++) 

     // { 

     // System.out.println((byte)buffer[i]); 

     // } 

     // System.out.println((short)0); 

     // inform the JCRE that the applet has data to return 

     short le = apdu.setOutgoing(); 

     // set the actual number of the outgoing data bytes 

     apdu.setOutgoingLength((byte) 2); 

     // write the balance into the APDU buffer at the offset 0 

     Util.setShort(buffer, (short) 0, balance); 

     // send the 2-byte balance at the offset 

     // 0 in the apdu buffer 

     apdu.sendBytes((short) 0, (short) 2); 

    } // end of getBalance method 

    /** 
    * 
    * verify the PIN 
    */ 

    private void verify(APDU apdu) { 

     byte[] buffer = apdu.getBuffer(); 

     // receive the PIN data for validation. 

     byte byteRead = (byte) (apdu.setIncomingAndReceive()); 

     // check pin 

     // the PIN data is read into the APDU buffer 

     // starting at the offset ISO7816.OFFSET_CDATA 

     // the PIN data length = byteRead 

     if (pin.check(buffer, ISO7816.OFFSET_CDATA, byteRead) == false) 

      ISOException.throwIt(SW_VERIFICATION_FAILED); 

    } // end of verify method 

} 

Antwort

0

Wie funktioniert der Simulator?

Netbeans verwendet Java Card Development Kit-Tools, um Java Card zu simulieren. Die Kommunikation mit dem Simulator erfordert eine kleine Socket-Programmierung, aber die JCDK hat dafür bereits eine Bibliothek bereitgestellt. Es heißt APDUIO. Sie finden es und its documentations in der JCDK.

Diejenigen Anschlüsse, die Netbeans zum Simulator zuweisen ist 9025 (Kontakt) und 9026 (zur berührungslosen) voreingestellt. Aber Sie können sie einfach ändern.

Wie ändern Sie Java Card Simulator-Konfigurationen in Netbeans?

1-Zum Dienstleistungen Registerkarte tun einen Rechtsklick auf Java Card Runtime und wählen Sie dann Java-Plattformen:

enter image description here

2- Wählen gebündelten Java Card und Klicken Sie dann auf Geräte verwalten:

enter image description here

3- Dort können Sie die konfigurierten Ports ändern:

enter image description here

Wie mit dem Simulator über den Code kommunizieren?

Erste wiederum auf dem Simulator in der Netbeans, und dann dieses Programm ausführen:

package testapduio; 

import com.sun.javacard.apduio.*; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.net.Socket; 
import java.util.Arrays; 

public class TestAPDUIO { 

    public static void main(String[] args) { 

     CadClientInterface cad; 
     Socket sock; 
     Apdu apdu = new Apdu(); 
     apdu.command = new byte[]{(byte) 0x00, (byte) 0xa4, (byte) 0x04, (byte) 0x00, (byte) 0x00}; 

     try { 
      sock = new Socket("localhost", 9025); 
      InputStream is = sock.getInputStream(); 
      OutputStream os = sock.getOutputStream(); 
      cad = CadDevice.getCadClientInstance(CadDevice.PROTOCOL_T1, is, os); 

      byte[] ATR = cad.powerUp(); 
      System.out.println("Answer To Reset:\n"); 
      System.out.println(Arrays.toString(ATR)); 

      byte[] input = apdu.getDataIn(); 
      byte[] output = apdu.getDataOut(); 
      System.out.println("-----------------"); 
      System.out.println(input); 
      System.out.println("\n"); 
      System.out.println(output); 

      cad.exchangeApdu(apdu); 
      System.out.println("-----------------"); 
      System.out.println(input); 
      System.out.println("\n"); 
      System.out.println(output); 

      cad.powerDown(); 
     } catch (Exception e) { 
      System.out.println("Exception Occurred"); 
     } 

    } 

} 

Beachten Sie, dass, wie Sie in den import s oben zu sehen, müssen Sie die apduio Bibliothek von Java Card hinzufügen Development Kit-Paket, zu Ihrer Projektbibliothek in Netbeans.

+0

Leider kann ich den Code jetzt nicht überprüfen. Es könnte ein Problem haben. Wenn Sie Probleme damit haben, lassen Sie es mich bitte wissen. – EbraHim

+0

Vielen Dank @EbraHim, aber es gibt einen Fehler auf der ** import com.sun.javacard.apduio. *; **. Dieses Paket kann nicht gefunden werden. –

+0

@diddiedee Wie ich unten den Code in meiner Antwort sagte, müssen Sie diese Datei zu Ihren Projektbibliotheken hinzufügen. Sie finden die JAR-Datei im Verzeichnis JCDK lib, – EbraHim

Verwandte Themen