2014-01-22 5 views
4

Я начинаю открывать Java-карту, скопировал код из образца. так или иначе, я смог как часть кода работает. Но все еще путают следующее.Работа с картой Java Card

. Способ работы владельца и как и когда установлен контакт . Как сделать кредитные и дебетовые работы

Я понимаю, как работает баланс, и этот аспект является prety ok. Ниже приведен код

wallet.java

/* 
* To change this template, choose Tools | Templates 
* and open the template in the editor. 
*/ 
package classicapplet1; 

import javacard.framework.APDU; 
import javacard.framework.Applet; 
import javacard.framework.ISO7816; 
import javacard.framework.ISOException; 
import javacard.framework.OwnerPIN; 

public class Wallet extends Applet { 

    /* constants declaration */ 
    // code of CLA byte in the command APDU header 
    final static byte Wallet_CLA = (byte) 0x80; 
    // codes of INS byte in the command APDU header 
    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 balance 
    final static short MAX_BALANCE = 0x7FFF; 
    // maximum transaction amount 
    final static byte MAX_TRANSACTION_AMOUNT = 127; 
    // 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; 
    // signal that the PIN verification failed 
    final static short SW_VERIFICATION_FAILED = 0x6300; 
    // signal the the PIN validation is required 
    // for a credit or a debit transaction 
    final static short SW_PIN_VERIFICATION_REQUIRED = 0x6301; 
    // signal invalid transaction amount 
    // amount > MAX_TRANSACTION_AMOUNT or amount < 0 
    final static short SW_INVALID_TRANSACTION_AMOUNT = 0x6A83; 
    // signal that the balance exceed the maximum 
    final static short SW_EXCEED_MAXIMUM_BALANCE = 0x6A84; 
    // signal the the balance becomes negative 
    final static short SW_NEGATIVE_BALANCE = 0x6A85; 

    /* instance variables declaration */ 
    OwnerPIN pin; 
    short balance; 

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

     // It is good programming practice to allocate 
     // all the memory that an applet needs during 
     // its lifetime inside the constructor 
     pin = new OwnerPIN(PIN_TRY_LIMIT, MAX_PIN_SIZE); 

     byte iLen = bArray[bOffset]; // aid length 
     bOffset = (short) (bOffset + iLen + 1); 
     byte cLen = bArray[bOffset]; // info length 
     bOffset = (short) (bOffset + cLen + 1); 
     byte aLen = bArray[bOffset]; // applet data length 

     // The installation parameters contain the PIN 
     // initialization value 
     pin.update(bArray, (short) (bOffset + 1), aLen); 
     register(); 

    } // end of the constructor 

    public static void install(byte[] bArray, short bOffset, byte bLength) { 
     // create a Wallet applet instance 
     new Wallet(bArray, bOffset, bLength); 
    } // end of install method 

    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 

    public void deselect() { 

     // reset the pin value 
     pin.reset(); 

    } 

    public void process(APDU apdu) { 

     // APDU object carries a byte array (buffer) to 
     // transfer incoming and outgoing APDU header 
     // and data bytes between card and CAD 

     // At this point, only the first header bytes 
     // [CLA, INS, P1, P2, P3] are available in 
     // the APDU buffer. 
     // The interface javacard.framework.ISO7816 
     // declares constants to denote the offset of 
     // these bytes in the APDU buffer 

     byte[] buffer = apdu.getBuffer(); 
     // check SELECT APDU command 

     if (apdu.isISOInterindustryCLA()) { 
      if (buffer[ISO7816.OFFSET_INS] == (byte) (0xA4)) { 
       return; 
      } 
      ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED); 
     } 

     // verify the reset of commands have the 
     // correct CLA byte, which specifies the 
     // command structure 
     if (buffer[ISO7816.OFFSET_CLA] != Wallet_CLA) { 
      ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED); 
     } 

     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 

    private void credit(APDU apdu) { 

     // access authentication 
     if (!pin.isValidated()) { 
      ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED); 
     } 

     byte[] buffer = apdu.getBuffer(); 

     // Lc byte denotes the number of bytes in the 
     // data field of the command APDU 
     byte numBytes = buffer[ISO7816.OFFSET_LC]; 

     // indicate that this APDU has incoming data 
     // and receive data starting from the offset 
     // ISO7816.OFFSET_CDATA following the 5 header 
     // bytes. 
     byte byteRead = (byte) (apdu.setIncomingAndReceive()); 

     // it is an error if the number of data bytes 
     // read does not match the number in 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); 

    } // end of deposit method 

    private void debit(APDU apdu) { 

     // access authentication 
     if (!pin.isValidated()) { 
      ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED); 
     } 

     byte[] buffer = apdu.getBuffer(); 

     byte numBytes = (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 

    private void getBalance(APDU apdu) { 

     byte[] buffer = apdu.getBuffer(); 

     // inform system that the applet has finished 
     // processing the command and the system should 
     // now prepare to construct a response APDU 
     // which contains data field 
     short le = apdu.setOutgoing(); 

     if (le < 2) { 
      ISOException.throwIt((byte) 0x6A86); 
     } 

     // informs the CAD the actual number of bytes 
     // returned 
     apdu.setOutgoingLength((byte) 2); 

     // move the balance data into the APDU buffer 
     // starting at the offset 0 
     buffer[0] = (byte) (balance >> 8); 
     buffer[1] = (byte) (balance & 0xFF); 

     // send the 2-byte balance at the offset 
     // 0 in the apdu buffer 
     apdu.sendBytes((short) 0, (short) 2); 

    } // end of getBalance method 

    private void verify(APDU apdu) { 

     byte[] buffer = apdu.getBuffer(); 
     // retrieve the PIN data for validation. 
     byte byteRead = (byte) (apdu.setIncomingAndReceive()); 

     // check pin 
     // the PIN data is read into the APDU buffer 
     // 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 validate method 
} // end of class Wallet 

и ниже ОПЗ файл wallet.scr

//Test script for Applet 'Wallet' 

powerup; 
// Select Wallet //aid/27ADED2B70/39 
0x00 0xA4 0x04 0x00 0X06 0X27 0XAD 0XED 0X2B 0X70 0X3A 0x7F; 

//Send the APDU here 
//0x80 0xCA 0x00 0x00 <length> <data> 0x7F; 
0x80 0x50 0x00 0x00 0x00 0x7F; 
powerdown; 

выше wallet.scr, я использовал, чтобы проверить баланс и отъезда положить:

CLA: 80, INS: 50, P1: 00, P2: 00, Lc: 00, Le: 02, 00, 00, SW1: 90, SW2: 00 

который ожидается. Но когда я пытаюсь кредитовать и дебетовать, как я должен это делать? Заранее спасибо

ответ

5

Чтобы позвонить в кредит (или дебетовой) методы, необходимые для изменения INS байт вашего APDU, чтобы соответствовать требуемой величины.

В коде вы выложили INS для Кредита является 0x30 и INS для дебета является 0x40.

Таким образом, после отправки выберите APDU вам необходимо будет направить следующие

кредитных

0x80 0x30 0x00 0x00 0x01 (1 byte containing the Credit value) 0x00 

дебет

0x80 0x30 0x00 0x00 0x01 (1 byte containing the Debit value) 0x00 

В обоих случаях вы должны Получать 0x63 0x61 в ответ с указанием что вам необходимо выполнить команду Проверить PIN-код.

Проверка PIN команды должны быть построены как:

0x80 0x20 0x00 0x00 (1 byte indicating the number of PIN bytes) (The PIN bytes) 0x00 

, например, если PIN-код был 4 цифры и устанавливается на значение «1234» можно было бы ожидать, чтобы увидеть следующее:

0x80 0x20 0x00 0x00 0x02 0x12 0x34 0x00 

Если ПИН-код проверяется правильно, вы получите 0x90 0x00 в ответ

Если ПИН-код неправильно вы получите ответ 0x63 0x00

Значение PIN-кода для этого приложения устанавливается в установки Parameters апплета, который как следует из названия, когда установлен апплет на карту (или эмулятор)

Надеется, что это помогает

+0

очень хороший ответ. Спасибо слот. Пожалуйста, где я получу материал. Для предварительного учебника @shortman –

+0

Я бы предложил дать этой книге «Технология Java Card для смарт-карт Zhiqun Chen». Я все еще использую ее в качестве справочника, когда у меня возникают проблемы. – ShortMan

Смежные вопросы