使用 APDU 在 Netbeans 中查询 Javacard Applet

Querying Javacard Applet in Netbeans using APDUs

我是智能卡 javacard applet 开发的新手。我得到了几乎所有文档都引用的经典小程序代码。但是,我无法使用 netbeans 中的命令 APDU 运行 或查询卡(运行 执行这些操作 验证、信用、借记、获取余额)。您能否分享成功响应的命令片段。

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

}

为了制作这个程序 运行,当你在安装时输入验证密钥时,我会快速编写代码,

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

这里我提供密钥:-

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

在设置 like 的帮助下,所以我相应地为 pin.update() 函数编写代码。

现在我发射了一些命令来测试这个小程序,结果如下。

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]

希望这就是您要找的。我发现 update key 部分真的很棘手,因为你是这里的新手。按照图片进行设置并通过发送更多命令来测试您的小程序。