我想知道是否有人可以帮助我,因为我是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文件以及生成的创建和选择小程序脚本,并且一切正常。 我遇到的问题是当我尝试运行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>
很抱歉,如果这很长,可能是一个非常简单的问题,但我没有意识到,当我接受这个项目时,这就是它会发生的事情(哈哈哈!我知道!),但我一直在这两天并尝试了各种各样的事情无济于事,所以如果你们中的任何一个人能帮助我,我会非常感激!
答案 0 :(得分:0)
Ne的值,最大要返回的字节数被编码到名为Le的字节表示中。可以通过调用setOutgoing
从applet中检索Ne的值(检查返回值!)。这也将处理Ne = 256的编码的转换,这是Le设置为00
。
因此,您可以检查Ne是否足够大以容纳您的数据。如果是这种情况,您可以退货。返回的数据少于请求的数据。否则你可能仍然需要&#34;抛出&#34; 6700
长度无效的状态字。
你的命令:
0x80 0x09 0x00 0x02 0x00 0x7F
当然不正确。命令数据大小(Nc)的编码Lc简单地是空字符串,即Lc从命令APDU 不存在。所以你在这里展示的是Le = 0x00
,它在你的代码中被错误地解释为Ne = 0。然后有一个伪字节设置为0x7F
。
结合我上面的评论,您应该能够发送:
0x80 0x09 0x00 0x02 0x00
这样Le = 0x00被解释为Ne的最大大小为256.如果你的数据适合于那,那么返回它。如果它不合适,你必须检查命令链或扩展长度APDU(但根据你的单个APDU写命令,它很容易适合 - 这只是对未来读者的一个评论)。
答案 1 :(得分:0)
感谢所有有帮助的人......我真的很感激..我总是使用这个网站,并且羡慕你们所有人利用你们的空闲时间来帮助像我这样的人(免费!),谢谢!
我设法让它上班...... 基本上我做了这个..
&#39;你可以尝试改变行if(le == 0)ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); if(le == 0)le =(short)(SIZE_MEMORY - offset);?我从来没有使用过这个模拟器,但是这个0x7F附加到APDU是什么(对我来说没有任何意义)? - vlp&#39;
......然后我把这条线放在线前; &#39; if((offset + le)&gt; SIZE_MEMORY)......并且它有效! - 再次非常感谢!