我想知道是否有人可以帮助我,因为我是Java的新手?!我有一个读/写小程序,我从这里的代码开发(基本相同,只是更改了指令代码和小程序名称)(http://www.wrankl.de/Javacard/ReadWriteJava.txt),如下所示:
// @(#)SmartTransfer.java 1.0 07/05/17
//Applet package package smartTransfer;
import javacard.framework.*;
//Transfer class extends the base Applet class
public class Transfer extends Applet {
// Declare constants
// code of instruction class; CLA - First (1 byte) - in the command APDU header
final static byte CLASS = (byte) 0x80;
// codes of INS byte in the command APDU header - for write instruction
final static byte WRITE_USER_INFO_INS = 0x07;
// codes of INS byte in the command APDU header - for read instruction
final static byte READ_USER_INFO_INS = 0x09;
// Size of storage area
final static byte SIZE_MEMORY = (short) 9;
static byte[] memory;
//Member variables - contain values for objects
//OwnerPIN pin;
/************************************/
// Installs the Applet, constructs the transfer object and registers with JCRE
public static void install(byte[] bArray, short bOffset, byte bLength) throws ISOException {
new Transfer().register();
memory = new byte[SIZE_MEMORY];
}
/************************************/
// Processing the APDU commands
@Override
public void process(APDU apdu)
throws ISOException {
if (selectingApplet()) return;
byte[] buffer = apdu.getBuffer();
if (buffer[ISO7816.OFFSET_CLA] !=CLASS) {
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
}
byte ins = buffer[ISO7816.OFFSET_INS];
switch (ins) {
case READ_USER_INFO_INS:
readUserInfo(apdu);
break;
case WRITE_USER_INFO_INS:
writeUserInfo(apdu);
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
}
private void writeUserInfo(APDU apdu) {
byte[] cmd_apdu = apdu.getBuffer();
// check if P1=0
if (cmd_apdu[ISO7816.OFFSET_P1] != 0)
ISOException.throwIt(ISO7816.SW_WRONG_P1P2);
// check if offset P2 is inside the bound of the memory array
short offset = (short) (cmd_apdu[ISO7816.OFFSET_P2] & 0x00FF);
// calculate offset
if (offset >= SIZE_MEMORY)
ISOException.throwIt(ISO7816.SW_WRONG_P1P2);
// check if expected length is within the memory array
short lc = (short)(cmd_apdu[ISO7816.OFFSET_LC] & 0x00FF);
// check no. off bytes against that in memory object
if ((offset + lc) > SIZE_MEMORY)
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
// check there are bytes in the command
if (lc == 0)
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
// points to method to get rest of the APDU
getAPDUBody(apdu);
//Data copied to the memory - atomic procedure
Util.arrayCopy(cmd_apdu, (short)((ISO7816.OFFSET_CDATA) & 0x00FF), memory, offset, lc);
// command complete message
ISOException.throwIt(ISO7816.SW_NO_ERROR);
}
//Receive the body of the command APDU method
public void getAPDUBody(APDU apdu) {
byte[] buffer = apdu.getBuffer();
// check expected length against actual length in command APDU body
short lc = (short)(buffer[ISO7816.OFFSET_LC] & 0x00FF);
// If not send error message`
if (lc != apdu.setIncomingAndReceive())
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
private void readUserInfo(APDU apdu) {
byte[] cmd_apdu = apdu.getBuffer();
//----- check the preconditions -----
// check if P1=0
if (cmd_apdu[ISO7816.OFFSET_P1] != 0) ISOException.throwIt(ISO7816.SW_WRONG_P1P2);
// check if offset P2 is inside the bound of the memory array
short offset = (short) (cmd_apdu[ISO7816.OFFSET_P2] & 0x00FF); // calculate offset
if (offset >= SIZE_MEMORY) ISOException.throwIt(ISO7816.SW_WRONG_P1P2);
// check if offset P2 and expected length Le is inside the bounds of the memory array
short le = (short)(cmd_apdu[ISO7816.OFFSET_LC] & 0x00FF);
if ((offset + le) > SIZE_MEMORY) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
// check if expected length Le of return bytes is 0
if (le == 0) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
// set transmission to outgoing data
apdu.setOutgoing();
// set the number of bytes to send to the IFD
apdu.setOutgoingLength((short)le);
// send the requested number of bytes to the IFD
apdu.sendBytesLong(memory, (short)offset, (short)le);
}
}
我正在使用Eclipse IDE中的CREF JavaCard模拟器并运行CAP文件以及生成的创建和选择applet脚本,并且一切正常 . 我遇到的问题是当我尝试运行read apdu时 . 下面的写命令示例和我尝试的任何内容(在代码中由writeUserinfo APDU方法设置的边界内)都可以工作,但无论我尝试使用readUserInfo APDU,都无效 . 我要么接收数据输入长度!= Lc或Le = 00 | SW1 SW2:6700 . 我知道这些意思是什么,但我已经尝试了所有我能想到或从现有文献中找到的东西,似乎没有任何效果 . 据我所知,网站上已经说过这个小程序已经过试用和测试,但我还没有收到javacard来测试它是否区分支持,因为我还读到模拟器是基于一个旧的JavaCard .
这是我正在使用的写apdu的一个例子:
//Select Transfer applet
0x00 0xA4 0x04 0x00 0x07 0xFF 0x00 0x20 0x00 0x00 0x00 0x20 0x7F;
APDU|CLA: 00, INS: a4, P1: 04, P2: 00, Lc: 07, ff, 00, 20, 00, 00, 00, 20, Le: 00, SW1: 90, SW2: 00
//Write Ross to memory byte array at offset 2
CMD>0x80 0x07 0x00 0x02 0x04 0x52 0x6f 0x73 0x73 0x7F;
APDU|CLA: 80, INS: 07, P1: 00, P2: 02, Lc: 04, 52, 6f, 73, 73, Le: 00, SW1: 90, SW2: 00
然后这里是所有类型的读APDU我试图从偏移2读取4个字节;
首先我尝试了le = 4字节CMD> 0x80 0x09 0x00 0x02 0x04 0x7F; CREF | C-JCRE已关闭 .
CREF exited with code 0
User input thread exited
ApduTool thread exited
ApduTool process finished with code: 1
APDU|Input data length != Lc around line 50.
我还读到使用CREF是卡级别而不是终端级别所以不需要指定le字段,所以我试过;
CMD>0x80 0x09 0x00 0x02 0x00 0x7F;
APDU|CLA: 80, INS: 09, P1: 00, P2: 02, Lc: 00, Le: 00, SW1: 67, SW2: 00
我还尝试写入许多不同的偏移量,改变内存字节数组的长度 . 我将内存字节数组对象更改为applet install(因为我认为这可能会在applet中创建对象) . 我尝试在读取和写入方法中取出Lc = 0的检查(因为这影响了我读到的Le = 0) . 我尝试将写入和读取命令更改为不包括0x7F,因为这被解释为其他东西);写命令成功的地方; 9000,但是当我运行没有0x7F的读命令时,我得到了这个响应; CMD> 0x80 0x09 0x00 0x02 0x00; CREF | C-JCRE已关闭 .
CREF exited with code 0
User input thread exited
ApduTool thread exited
ApduTool process finished with code: 1
APDU|Invalid Token after "0x00", was expecting one of <INTEGER_LITERAL> <CHARACTER_LITERAL> <STRING_LITERAL>
对不起,如果这很长,可能是一个非常简单的问题,但我没有意识到,当我接受这个项目时,这就是它会发生的事情(哈哈哈!我知道!),但我一直在这两个天和尝试了各种各样的事情无济于事所以,如果你们中的任何一个好人可以帮助我,我会非常感激!
2 回答
要返回的最大字节数Ne的值被编码到称为Le的字节表示中 . 可以通过调用
setOutgoing
(检查返回值!)从applet中简单地检索Ne的值 . 这也将处理Ne = 256的编码的转换,这是Le设置为00
.因此,您可以检查Ne是否足够大以容纳您的数据 . 如果是这种情况,您可以退货 . 返回的数据少于请求的数据 . 否则,您可能仍需要"throw"
6700
长度的无效状态字 .你的命令:
当然不正确 . 命令数据大小(Nc)的编码Lc简单地是空字符串,即命令APDU中不存在Lc . 所以你在这里展示的是Le =
0x00
,它在你的代码中被错误地解释为Ne = 0 . 然后有一个伪字节设置为0x7F
.结合我上面的评论,你应该能够发送:
因此,Le = 0x00被解释为Ne的最大大小为256.如果您的数据适合于此,则返回它 . 如果它不适合你必须检查命令链或扩展长度APDU(但根据你的单个APDU写命令它很容易适合 - 这只是未来读者的一个评论) .
谢谢所有有帮助的人...我真的很感激..我总是使用这个网站,并且羡慕所有人利用你的空闲时间来帮助像我这样的人(免费!),谢谢!
我设法让它工作......基本上我做了这个..
'你可以尝试改变行if(le == 0)ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); if(le == 0)le =(short)(SIZE_MEMORY - offset);?我从来没有使用过这个模拟器,但是这个0x7F附加到APDU上是什么(对我来说没有任何意义)? - vlp'
......然后我把这条线放在线前; 'if((offset le)> SIZE_MEMORY)......它有效! - 再次非常感谢!