简体   繁体   中英

Querying Javacard Applet in Netbeans using APDUs

I am a newbie in javacard applet development for smart cards. I got the classic applet code that almost all documents reference. However, I am failing to run or query the card ( running these operations verify,credit,debit,getbalance) using command APDUs in netbeans. Could you kindly share the commands sniplet with a success response.

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

}

For making this program running , As you are putting verify key at install time I do quick code like ,

 pin.update(bArray, (short) (bOffset + 9), (byte) 0x8);

here I am providing key :-

0X11 0X22 0X33 0X44 0X55 0X66 0X77 0X88

with help of setting like, and so I code accordingly for pin.update() function. 你可以在这里设置安装参数

now I fired some of the command to test this applet and result is as below.

ApduTool [v3.0.2]
    Copyright (c) 2009 Sun Microsystems, Inc.
    All rights reserved.
    Use is subject to license terms.
Opening connection to localhost on port 9025.
Connected.
Received ATR = 0x3b 0xf0 0x11 0x00 0xff 0x00 
CLA: 00, INS: a4, P1: 04, P2: 00, Lc: 06, 68, ea, 30, 8d, 42, df, Le: 00, SW1: 90, SW2: 00
CLA: b0, INS: 50, P1: 00, P2: 00, Lc: 00, Le: 02, 00, 00, SW1: 90, SW2: 00 [Get Balance]
CLA: b0, INS: 30, P1: 00, P2: 00, Lc: 02, 00, 10, Le: 00, SW1: 63, SW2: 01 [ Credit]
CLA: b0, INS: 20, P1: 00, P2: 00, Lc: 08, 11, 22, 33, 44, 55, 66, 77, 88, Le: 00, SW1: 90, SW2: 00 [ Verify]
CLA: b0, INS: 30, P1: 00, P2: 00, Lc: 02, 00, 10, Le: 00, SW1: 67, SW2: 00 [ Credit]
CLA: b0, INS: 30, P1: 00, P2: 00, Lc: 01, 10, Le: 00, SW1: 90, SW2: 00 [Credit]
CLA: b0, INS: 50, P1: 00, P2: 00, Lc: 00, Le: 02, 00, 10, SW1: 90, SW2: 00 [ Get Balance]

Hope this is what you are looking for. I found update key Portion is really tricky as you are newbie here. Do setting as per picture and test your applet with sending more number of commands.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM