2016-05-01 5 views
0

Я новичок в мире джавакар. У меня есть аппликатор кошелька, успешно работающий в netbeans (я могу кредитовать, дебетовать, проверять баланс, проверять PIN-код и т. Д., Используя APDU в консоли устройства). Мне поручено написать приложение-хост для связи с этой картой в netbeans без использования консоли смарт-карты. Из небольшого исследования я полагаю, что мне нужно импортировать класс javax.smartcardio в мое хост-приложение, однако, как вы, возможно, знаете, документации очень мало. Любая помощь будет оценена и поможет многим из нас, которым трудно усвоить этот мир программирования смарт-карт. Ниже мой код апплета. Штыр передавался через параметры как 1122334455667788 через свойства проекта.Как приложение-хост может запрашивать javacard-апплет на моделируемой смарт-карте в Netbeans?

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 

} 

ответ

0

Как работает тренажер?

Netbeans использует инструменты разработки Java-карт для моделирования Java-карты. Общение с симулятором требует небольшого программирования сокетов, но JCDK предоставил библиотеку для этого уже. Он называется APDUIO. Вы можете найти его и its documentations в JCDK.

Тех порты, которые Netbeans назначаемых тренажер 9025 (для контакта) и 9026 (для бесконтактного) по умолчанию. Но вы можете просто изменить их.

Как изменить конфигурации симулятора Java-карты в Netbeans?

1-К Услуги вкладку, сделать правой кнопкой мыши на Java карты Время воспроизведения, а затем выберите Java платформы:

enter image description here

2- Выберите Bundled Java Card и затем щелкните по адресу Устройства управления:

enter image description here

3- Там вы можете изменить настроенные порты:

enter image description here

Как общаться с имитатором через код?

Первый поворот на тренажере в Netbeans, а затем запустить эту программу:

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"); 
     } 

    } 

} 

Обратите внимание, что, как вы видите в import с выше, вам нужно добавить apduio библиотеку из Java Card Пакета разработчика, в библиотеку вашего проекта в Netbeans.

+0

К сожалению, я не могу проверить код сейчас. Это может иметь некоторые проблемы. Если у вас есть проблемы с этим, сообщите мне. – EbraHim

+0

Спасибо большое @EbraHim, но есть ошибка в ** import com.sun.javacard.apduio. *; **. Этот пакет не найден. –

+0

@diddiedee Как я сказал ниже в моем ответе, вам нужно добавить этот файл в свои библиотеки проектов. Вы можете найти его файл jar в каталоге JCDK lib, – EbraHim