Я новичок в мире джавакар. У меня есть аппликатор кошелька, успешно работающий в 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
}
К сожалению, я не могу проверить код сейчас. Это может иметь некоторые проблемы. Если у вас есть проблемы с этим, сообщите мне. – EbraHim
Спасибо большое @EbraHim, но есть ошибка в ** import com.sun.javacard.apduio. *; **. Этот пакет не найден. –
@diddiedee Как я сказал ниже в моем ответе, вам нужно добавить этот файл в свои библиотеки проектов. Вы можете найти его файл jar в каталоге JCDK lib, – EbraHim