Arrays 如何将数据数组发送到我的小程序,并由小程序对其进行操作,并在apdu响应中返回新数据?

Arrays 如何将数据数组发送到我的小程序,并由小程序对其进行操作,并在apdu响应中返回新数据?,arrays,applet,javacard,apdu,Arrays,Applet,Javacard,Apdu,更新1: 我在javacard上安装了我的小程序(我使用的源代码是我的问题中公认的答案)。当我通过OpenSc发送generatedKey命令时,它只返回9000作为响应,而不是发送XORed数据!我用Javacard版本2.2.1创建了我的项目,我确信我的卡与该版本兼容。为什么OpenSc没有收到预期的数据 我想向我的JavaCard小程序发送一个包含24个元素的随机字节数组,然后我的小程序应该使用特定的方法更改该数组。例如,该方法将每个元素与0x05异或,并在APDU响应中返回结果数组 为

更新1: 我在javacard上安装了我的小程序(我使用的源代码是我的问题中公认的答案)。当我通过OpenSc发送generatedKey命令时,它只返回9000作为响应,而不是发送XORed数据!我用Javacard版本2.2.1创建了我的项目,我确信我的卡与该版本兼容。为什么OpenSc没有收到预期的数据


我想向我的JavaCard小程序发送一个包含24个元素的随机字节数组,然后我的小程序应该使用特定的方法更改该数组。例如,该方法将每个元素与
0x05
异或,并在APDU响应中返回结果数组

为了实现上述目标,到目前为止,我编写了以下程序:

package keyGeneratorPackage;
import javacard.framework.*;

public class keyGeneratorPackage extends Applet {

    private static final byte HW_CLA = (byte) 0x80;
    private static final byte HW_INS = (byte) 0x00;

    public static void install(byte[] bArray, short bOffset, byte bLength) {
        new keyGeneratorPackage().register(bArray, (short) (bOffset + 1),
                bArray[bOffset]);
    }

    public void process(APDU apdu) {

        if (selectingApplet()) {
            return;
        }

        byte[] buffer = apdu.getBuffer();
        byte CLA = (byte) (buffer[ISO7816.OFFSET_CLA] & 0xFF);
        byte INS = (byte) (buffer[ISO7816.OFFSET_INS] & 0xFF);
        byte[] Data = new byte[] { (byte) (buffer[ISO7816.OFFSET_CDATA] & 0xFF) };

        if (CLA != HW_CLA) {
            ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
        }

        switch (INS) {
        case HW_INS:

            getKey(apdu, Data);
            break;

        default:
            ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
    }

    private void getKey(APDU apdu, byte[] data) {
        byte[] buffer = apdu.getBuffer();
        byte[] generatedKey = generateKey(data);
        short length = (short) generatedKey.length;

        Util.arrayCopyNonAtomic(generatedKey, (short) 0, buffer, (short) 0,
                (short) length);

        apdu.setOutgoingAndSend((short) 0, length);
    }

    private byte[] generateKey(byte[] Data) {
        byte[] key = new byte[] { (byte) 0x00 };
        for (int i = 0; i < Data.length; i++) {
            key[i] = (byte) (Data[i] ^ 5);
        }
        return key;
    }

}
包密钥生成器包;
导入javacard.framework.*;
公共类keyGeneratorPackage扩展小程序{
私有静态最终字节HW_CLA=(字节)0x80;
私有静态最终字节HW_INS=(字节)0x00;
公共静态无效安装(字节[]bArray,短bOffset,字节bLength){
新的keyGeneratorPackage().寄存器(bArray,(短)(bOffset+1),
巴里[博夫特];
}
公共作废流程(APDU APDU){
如果(选择Applet()){
返回;
}
byte[]buffer=apdu.getBuffer();
字节CLA=(字节)(缓冲区[ISO7816.OFFSET_CLA]&0xFF);
字节INS=(字节)(缓冲区[ISO7816.OFFSET_INS]&0xFF);
字节[]数据=新字节[]{(字节)(缓冲区[ISO7816.OFFSET\U CDATA]&0xFF)};
如果(CLA!=HW_CLA){
ISOException.throwIt(不支持ISO7816.SW_CLA_);
}
开关(INS){
案例硬件插件:
getKey(apdu,数据);
打破
违约:
ISOException.throwIt(ISO7816.SW不支持);
}
}
私有void getKey(APDU APDU,字节[]数据){
byte[]buffer=apdu.getBuffer();
字节[]生成键=生成键(数据);
短长度=(短)generatedKey.length;
Util.arrayCopyNonAtomic(generatedKey,(short)0,buffer,(short)0,
(短)长度);
apdu.setOutgoingAndSend((短)0,长度);
}
专用字节[]生成键(字节[]数据){
字节[]键=新字节[]{(字节)0x00};
对于(int i=0;i
编译并选择小程序后,我必须发送以下APDU命令:

>>80 00 00 00 18 11 22 33 44 55 66 77 88 99 10 20 30 40 50 60 70 80 90 b1 b2 b3 b4 b5 b6 b7 26


我的小程序有问题吗?

在方法中,
私有void getKey(APDU APDU,byte[]data)
您需要调用

apdu.setIncomingAndReceive();
记住:

这是主要的接收方法。调用此方法表示此APDU具有传入数据。此方法获取尽可能多的字节,以便在标头后面的APDU缓冲区中不出现缓冲区溢出。如果合适,它将获取所有传入的字节

因此,请按如下方式更新您的方法:

private void getKey( APDU apdu , byte[] data)
  {
      apdu.setIncomingAndReceive();
      byte[] buffer = apdu.getBuffer();
      byte[] generatedKey = generateKey(data);
      short length = (short) generatedKey.length;
      //short length =1;

      Util.arrayCopyNonAtomic(generatedKey, (short)0, buffer, (short)0, (short) length);

      apdu.setOutgoingAndSend((short)0, length);
}

注意:
setIncomingAndReceive
方法在Applet.process()方法中只能调用一次。有关更多详细信息,请阅读

编辑:代码中有几个问题。我一个接一个地提到它们

问题1:

byte[]Data=newbyte[]{(byte)(缓冲区[ISO7816.OFFSET\U CDATA]&0xFF)}

它创建长度为1的
字节[]数据
,值为
0x11

解决方案:
new
数据
持久EEP内存创建空间。如果不再需要
数据
,则可以将其设置为
瞬态
字节数组

像这样重写它(持久):

或者这个(暂时的):

问题2:

i) 您的
generateKey()
方法将崩溃,因为您正在创建
byte[]key
,这与您对
byte[]Data
所做的相同

ii)您不能声明
int i
,因为只有少数卡支持它,请使用
byte
short

解决方案:据我所知,在
generateKey()
方法中,您想做什么,我将其改写如下:

// the byte array preparation of key is the callers duty 
private byte[] generateKey(byte[] Data, byte[] key) {
    short i;
    for (i = 0; i < Data.length; i++) {
        key[i] = (byte) (Data[i] ^ (byte)0x05);
    }
    return key;
}
//键的字节数组准备是调用者的职责
专用字节[]生成键(字节[]数据,字节[]键){
短i;
对于(i=0;i
完整的工作代码为:

JavaCard:v.2.2.2

全球平台:v.2.1.1

建议:首先仔细阅读文档

package keyGeneratorPackage;

import javacard.framework.APDU;
import javacard.framework.ISO7816;
import javacard.framework.Applet;
import javacard.framework.ISOException;
import javacard.framework.JCSystem;
import javacard.framework.Util;

/**
 * KeyGeneratorPackage <br>
 * 
 * @author rakeb.void
 * 
 */
public class KeyGeneratorPackage extends Applet {
    private static final byte HW_CLA = (byte) 0x80;
    private static final byte HW_INS = (byte) 0x00;

    public static void install(byte[] bArray, short bOffset, byte bLength) {
        new keyGeneratorPackage.KeyGeneratorPackage().register(bArray, (short) (bOffset + 1),
                bArray[bOffset]);
    }

    public void process(APDU apdu) {
        if (selectingApplet()) {
            return;
        }
        apdu.setIncomingAndReceive();
        byte[] buffer = apdu.getBuffer();
        byte CLA = (byte) (buffer[ISO7816.OFFSET_CLA] & 0xFF);
        byte INS = (byte) (buffer[ISO7816.OFFSET_INS] & 0xFF);
        short  lc =  (short) (buffer[ISO7816.OFFSET_LC] & (short)0x00FF); 
//      byte[] Data = new byte[(byte) (buffer[ISO7816.OFFSET_LC] & 0xFF)];
        byte[] Data = JCSystem.makeTransientByteArray(lc, JCSystem.CLEAR_ON_DESELECT);

        if (CLA != HW_CLA) {
            ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
        }
        switch (INS) {
        case HW_INS: {
            // copying the apdu data into byte array Data
            Util.arrayCopy(buffer, ISO7816.OFFSET_CDATA, Data, (short) 0, lc);
            getKey(apdu, Data);
        }
        // you forget to put a break here!
        break;
        default:
            // good practice: If you don't know the INStruction, say so:
            ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
    }

    private void getKey(APDU apdu, byte[] data) {
        byte[] buffer = apdu.getBuffer();
        short length = (short) data.length;
        //prepareing the key array of same length of Data
        byte[] key = JCSystem.makeTransientByteArray(length, JCSystem.CLEAR_ON_DESELECT);
//      byte[] generatedKey = generateKey(data, key);
        // no need another array generatedKey, as we are passing key as parameter 
        generateKey(data, key);
//      length = (short) generatedKey.length;

        Util.arrayCopyNonAtomic(key, (short) 0, buffer, (short) 0, (short) length);

        apdu.setOutgoingAndSend((short) 0, length);
    }

    // .....................................
    private byte[] generateKey(byte[] Data, byte[] key) {
        short i;
        for (i = 0; i < Data.length; i++) {
            // i've no idea why you use 0x05 here,
            // in the question you mentioned 0x9D
            key[i] = (byte) (Data[i] ^ (byte)0x05); 
        } 
        return key;
    }

}
包密钥生成器包;
导入javacard.framework.APDU;
导入javacard.framework.ISO7816;
导入javacard.framework.Applet;
导入javacard.framework.ISOException;
导入javacard.framework.JCSystem;
导入javacard.framework.Util;
/**
*KeyGeneratorPackage
* *@author rakeb.void * */ 公共类KeyGeneratorPackage扩展小程序{ 私有静态最终字节HW_CLA=(字节)0x80; 私有静态最终字节HW_INS=(字节)0x00; 公共静态无效安装(字节[]bArray,短bOffset,字节bLength){ 新的keyGeneratorPackage.keyGeneratorPackage()寄存器(bArray,(短)(bOffset+1), 巴里[博夫特]; } 公共作废流程(APDU APDU){ 如果(选择Applet()){ 返回; } apdu.setIncomingAndReceive(); byte[]buffer=apdu.getBuffer(); 字节CLA=(字节)(缓冲区[ISO7816.OFFSET_CLA]&0xFF); 字节INS=(字节)(缓冲区[ISO7816.OFFSET_INS]&0xFF); 短lc=(短)(缓冲区[ISO7816.OFFSET_lc]&(短)0x00FF); //字节[]数据=新字节[(字节)(缓冲区[ISO7816.OFFSET_LC]&0xFF];
// the byte array preparation of key is the callers duty 
private byte[] generateKey(byte[] Data, byte[] key) {
    short i;
    for (i = 0; i < Data.length; i++) {
        key[i] = (byte) (Data[i] ^ (byte)0x05);
    }
    return key;
}
package keyGeneratorPackage;

import javacard.framework.APDU;
import javacard.framework.ISO7816;
import javacard.framework.Applet;
import javacard.framework.ISOException;
import javacard.framework.JCSystem;
import javacard.framework.Util;

/**
 * KeyGeneratorPackage <br>
 * 
 * @author rakeb.void
 * 
 */
public class KeyGeneratorPackage extends Applet {
    private static final byte HW_CLA = (byte) 0x80;
    private static final byte HW_INS = (byte) 0x00;

    public static void install(byte[] bArray, short bOffset, byte bLength) {
        new keyGeneratorPackage.KeyGeneratorPackage().register(bArray, (short) (bOffset + 1),
                bArray[bOffset]);
    }

    public void process(APDU apdu) {
        if (selectingApplet()) {
            return;
        }
        apdu.setIncomingAndReceive();
        byte[] buffer = apdu.getBuffer();
        byte CLA = (byte) (buffer[ISO7816.OFFSET_CLA] & 0xFF);
        byte INS = (byte) (buffer[ISO7816.OFFSET_INS] & 0xFF);
        short  lc =  (short) (buffer[ISO7816.OFFSET_LC] & (short)0x00FF); 
//      byte[] Data = new byte[(byte) (buffer[ISO7816.OFFSET_LC] & 0xFF)];
        byte[] Data = JCSystem.makeTransientByteArray(lc, JCSystem.CLEAR_ON_DESELECT);

        if (CLA != HW_CLA) {
            ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
        }
        switch (INS) {
        case HW_INS: {
            // copying the apdu data into byte array Data
            Util.arrayCopy(buffer, ISO7816.OFFSET_CDATA, Data, (short) 0, lc);
            getKey(apdu, Data);
        }
        // you forget to put a break here!
        break;
        default:
            // good practice: If you don't know the INStruction, say so:
            ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
    }

    private void getKey(APDU apdu, byte[] data) {
        byte[] buffer = apdu.getBuffer();
        short length = (short) data.length;
        //prepareing the key array of same length of Data
        byte[] key = JCSystem.makeTransientByteArray(length, JCSystem.CLEAR_ON_DESELECT);
//      byte[] generatedKey = generateKey(data, key);
        // no need another array generatedKey, as we are passing key as parameter 
        generateKey(data, key);
//      length = (short) generatedKey.length;

        Util.arrayCopyNonAtomic(key, (short) 0, buffer, (short) 0, (short) length);

        apdu.setOutgoingAndSend((short) 0, length);
    }

    // .....................................
    private byte[] generateKey(byte[] Data, byte[] key) {
        short i;
        for (i = 0; i < Data.length; i++) {
            // i've no idea why you use 0x05 here,
            // in the question you mentioned 0x9D
            key[i] = (byte) (Data[i] ^ (byte)0x05); 
        } 
        return key;
    }

}