2014-01-22 35 views
4

我是一個java卡初學者,從下面的代碼複製了樣本。不知何故,我已經能夠如何部分的代碼工作。但仍對以下內容感到困惑。使用Java Card錢包

。所有者引腳的工作方式以及引腳設置的方式和時間 。如何使信用卡和借記卡工程

我明白如何平衡的作品,這方面是不錯的。下面是代碼

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 

並且在下面的SCR文件 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

要叫你需要改變你的APDUINS字節,以匹配所需的值,信用(或借記卡)的方法。

在你的代碼已經發布了INS信用的0x30INS借記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 

如果PIN驗證正確你會得到一個的0x90爲0x00響應

如果PIN 不正確你會得到一個0x63爲0x00響應

PIN的爲這個應用程序的價值在設置爲小程序安裝參數這顧名思義,當小程序安裝到卡(或仿真器)上時

希望這有助於

+0

一個非常好的答案。謝謝槽。請,我在哪裏得到材料。對於高級教程@shortman –

+0

我建議爲本書提供一個閱讀「陳智羣的智能卡Java卡技術」,當我遇到問題時,我仍將其作爲參考。 – ShortMan