我正在使用JavaCard 2.2.2。
以下程序无效,因为ISO7816.SW_PIN_REQUIRED
找不到任何要解决的库。
如何将ISO7816.SW_PIN_REQUIRED
替换为任何其他常量以使程序运行?
package monpackage;
import javacard.framework.*;
//import javacardx.framework.*;
public class Wallet extends Applet
{
/* constants declaration */
// code of CLA byte in the command APDU header
final static byte Wallet_CLA =(byte)0xB0;
// codes of INS byte in the command APDU header
final static byte Deposit = (byte) 0x10;
final static byte Debit = (byte) 0x20;
final static byte Balance = (byte) 0x30;
final static byte Validate = (byte) 0x40;
// maximum number of incorrect tries before the
// PIN is blocked
final static byte PinTryLimit =(byte)0x03;
// maximum size PIN
final static byte MaxPinSize =(byte)0x04;
// status word (SW1-SW2) to signal that the
// balance becomes negative;
final static short SW_NEGATIVE_BALANCE = (short)0x6910;
/* instance variables declaration */
OwnerPIN pin;
byte balance;
byte buffer[]; // APDU buffer
private Wallet()
{
// It is good programming practice to allocate
// all the memory that an applet needs during
// its lifetime inside the constructor
pin = new OwnerPIN(PinTryLimit, MaxPinSize);
balance = 0;
register();
} // end of the constructor
public static void install(APDU apdu)
{
// create a Wallet applet instance
new Wallet();
} // end of install method
public boolean select()
{
// reset validation flag in the PIN object to
// false
pin.reset();
// returns true to JCRE to indicate that the
// applet is ready to accept incoming APDUs.
return true;
}// end of select method
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
buffer = apdu.getBuffer();
// verify that if the applet can accept this
// APDU message
if (buffer[ISO7816.OFFSET_CLA] !== Wallet_CLA)
{
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
}
switch (buffer[ISO7816.OFFSET_INS])
{
case Balance: getBalance(apdu); return;
case Debit: debit(apdu); return;
case Deposit: deposit(apdu);return;
case Validate: validate(apdu);return
default: ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
} // end of process method
private void deposit(APDU apdu) {
// access authentication
if ( ! pin.isValidated() )
ISOException.throwIt (ISO7816.SW_PIN_REQUIRED);
// Lc byte denotes the number of bytes in the
// data field of the comamnd APDU
byte numBytes = (byte) (buffer[ISO7816.OFFSET_LC]);
// indicate that this APDU has incoming data and
// receive data starting from the offset
// ISO.OFFSET_CDATA
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 (byteRead != 1)
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
// increase the balance by the amount specified
// in the data field of the command APDU.
balance = (byte)
(balance + buffer[ISO7816.OFFSET_CDATA]);
// return successfully
return;
} // end of deposit method
private void debit(APDU apdu) {
// access authentication
if ( ! pin.isValidated() )
ISOException.throwIt(ISO7816.SW_PIN_REQUIRED);
byte numBytes = (byte)(buffer[ISO7816.OFFSET_LC]);
byte byteRead =
(byte)(apdu.setIncomingAndReceive());
if (byteRead != 1)
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
// balance can not be negative
if ( ( balance - buffer[ISO7816.OFFSET_CDATA]) < 0 )
ISOException.throwIt(SW_NEGATIVE_BALANCE);
balance = (byte)
(balance - buffer[ISO7816.OFFSET_CDATA]);
} // end of debit method
private void getBalance(APDU apdu) {
// access authentication
if ( ! pin.isValidated() )
ISOException.throwIt(ISO7816.SW_PIN_REQUIRED);
// 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
apdu.setOutgoing();
//indicate the number of bytes in the data field
apdu.setOutgoingLength((byte)1);
// move the data into the APDU buffer starting
// at offset 0
buffer[0] = balance;
// send 1 byte of data at offset 0 in the APDU
// buffer
apdu.sendBytes((short)0, (short)1);
} // end of getBalance method
private void validate(APDU apdu) {
// retrieve the PIN data which requires to be
// valid ated. The user interface data is
// stored in the data field of the APDU
byte byteRead =
(byte)(apdu.setIncomingAndReceive());
// validate user interface and set the
// validation flag in the user interface
// object to be true if the validation.
// succeeds. If user interface validation
// fails, PinException would be thrown from
// the pin.check() method.
pin.check(buffer, ISO7816.OFFSET_CDATA, byteRead);
} // end of validate method
} // end of class Wallet
答案 0 :(得分:4)
再次查看Java Card 2.2.2 API Specifications - ISO7816 Interface。 :)
您将看到此界面中没有名为SW_PIN_REQUIRED
的字段。您只需在程序的常量声明部分添加以下行,然后将ISO.SW_PIN_REQUIRED
替换为SW_PIN_REQUIRED
。
final static short SW_PIN_REQUIRED = 0x6968
此外,您可以使用ISO7816
的以下已定义字段,而不是未定义字段SW_PIN_REQUIRED
:
ISO7816.SW_CONDITIONS_NOT_SATISFIED
或
ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED
BTW这些是规范中定义的一些特殊短值,您不必在程序中使用相同的值。例如,编译器在编译时将ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED
替换为0x6982
(如API规范中所述),当您与卡上的applet通信时,您将看到此值。因此,您只需定义特殊状态字,而不是使用这些值(不推荐)。
编辑(感谢Bodewes先生)
正如Bodewes先生在评论中所说,我们强烈建议您继续使用ISO/IEC 7816 - 3 Standard和4中定义的可能状态字范围。如果我们不这样做,我们可能会遇到麻烦,特别是对于T = 0(面向字节的接触模式)操作。
从7816-3:“如果值是'6X'或'9X',除了'60',它是一个SW1字节。它不要求数据传输动作。接口设备应等待一个字符传送SW2字节。对SW2值没有限制。“因此需要6X或9X才能与T = 0兼容。