我是一名java卡初学者,从样本中复制了以下代码。不知何故,我已经能够如何部分代码工作。但仍然对以下内容感到困惑。
。所有者工作的方式以及引脚设置的方式和时间 。如何使信用卡和借记卡工作
我理解平衡是如何工作的,那个方面是好的。以下是代码
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
这是预料之中的。但是,当我尝试信贷和借记时,我该怎么做?提前致谢
答案 0 :(得分:6)
要调用信用(或借记)方法,您需要更改 APDU 的 INS 字节以匹配所需的值。
在您发布的代码中,信用的 INS 为 0x30 ,而 INS 借方 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值在applet的安装参数中设置,顾名思义就是applet安装到卡片(或仿真器)上时
希望这有帮助