使用 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 部分真的很棘手,因为你是这里的新手。按照图片进行设置并通过发送更多命令来测试您的小程序。
我是智能卡 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 部分真的很棘手,因为你是这里的新手。按照图片进行设置并通过发送更多命令来测试您的小程序。