当前位置: 首页 > 知识库问答 >
问题:

为什么在CREF JavaCard Simulator的控制台中测试读写APDU时,我会收到输入数据长度!=Lc或SW1SW2:6700?

爱刚捷
2023-03-14
// @(#)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文件以及生成的create和select applet脚本,所有这些都正常工作。我遇到的问题是,当我试图运行读APDU的。下面的write命令示例和我尝试的任何方法(在代码中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字节;

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.
CMD>0x80 0x09 0x00 0x02 0x00 0x7F;
APDU|CLA: 80, INS: 09, P1: 00, P2: 02, Lc: 00, Le: 00, SW1: 67, SW2: 00
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>

很抱歉,如果这是一个很长的时间,可能是一个非常简单的问题,但我没有意识到当我接受这个项目时,这是它会出现的结果(对我来说lol!我知道!),但我已经在这个问题上两天了,尝试了各种事情都没有用,所以请如果你们中的任何一个好人能帮助我,我会非常伟大!

共有1个答案

易书
2023-03-14

Ne的值,返回的最大字节数被编码到称为LE的字节表示中。Ne的值可以通过调用setoutgoing从applet中检索(检查返回值!)。这还将处理Ne=256的编码转换,这是一个设置为00的Le。

因此,您可以检查Ne是否足够大以容纳您的数据。如果是这样的话,你可以把它退回去。返回的数据少于请求的数据是可以的。否则,您可能仍然必须“抛出”一个6700长度无效的状态字。

你的命令:

0x80 0x09 0x00 0x02 0x00 0x7F
0x80 0x09 0x00 0x02 0x00
 类似资料:
  • 我在Visual Studio中有一个测试项目。我使用Microsoft.VisualStudio.TestTools.UnitTesting。 我在我的一个单元测试中添加了这一行: 当我运行测试时,测试通过,但控制台窗口根本没有打开。 有没有办法让控制台窗口可以通过单元测试进行交互?

  • 问题内容: 我只有一种方法。如何检查System.out.println()并将Scanner替换为使用JUnit自动输入值? PS,请提供一些解决方案… 问题答案: 理想情况下,提取尴尬的依赖关系,以便您可以在没有依赖关系的情况下进行测试。更改为简单: (考虑使用a 代替for 。) 然后,您实际上不需要进行单元测试-但您可以使用基于的进行测试,并基于的输出进行测试,从而提供所需的任何输入并检查

  • 到目前为止,我有这个: 和这个: 当我测试这个时,它不能采取双倍数字,我收到这个消息: 我该如何解决这个问题?

  • 我刚刚开始学习Groovy,正在GroovyConsole中进行实验。 有没有办法读取用户输入?我尝试了下面的代码,但我得到了一个错误。 这是我收到的错误: 有什么我需要进口的吗? 任何帮助都会很好。 谢谢

  • 我试图实时调试一个C程序,它使用来自VScode的C/C++扩展,还允许我使用scanf()将直接输入写到控制台。但是,当我调试代码时,它打开调试控制台,不允许我输入任何输入。 我发现人们回答这个问题的两个线程: https://github.com/omnisharp/omnisharp-vscode/issues/1053 两者都建议将launch.json文件中的“Console”属性设置为

  • 我正在用jQuery做一件最简单、最基本的事情--从DOM中提取一个选择,然后将其打印到控制台。然而,我在控制台中看到的只是[object,object]。下面是我的js代码中的一行,它打印以控制台选择