简体   繁体   English

如何将数据数组发送到Applet并由Applet对其进行操作,并在响应apdu中返回新数据?

[英]How to send a data array to my Applet and manipulation it by Applet and return new data in response apdu?

Update 1: I installed my applet on the javacard(I used from the source code which is as accepted answer In my already question) .When I send generatedKey command via OpenSc ,It just returns 9000 as response instead of sending XORed Data! 更新1:我在Java卡上安装了applet(我从已经被接受的源代码中使用了我的源代码)。当我通过OpenSc发送generateKey命令时,它只是返回9000作为响应,而不是发送XORed数据! I created my project with Javacard version 2.2.1 and i am certain that my card is compattible with that version. 我使用Javacard 2.2.1版创建了项目,并且确定我的卡与该版本兼容。 Why expected data not recieved by OpenSc? 为什么OpenSc无法收到预期的数据?


I want to send a random byte array including for example 24 elements to my JavaCard applet and then my applet is supposed to change that array using a specific method. 我想向JavaCard applet发送一个包含例如24个元素的随机字节数组,然后我的applet应该使用特定方法更改该数组。 For example that method XOR each elements with 0x05 and returns the result array in APDU response. 例如,该方法将每个元素与0x05 XOR ,然后在APDU响应中返回结果数组。

To aim the above goal I wrote the following program so far: 为了实现上述目标,到目前为止,我编写了以下程序:

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;
    }

}

I must send the following APDU command after compiling and selecting my applet: 编译并选择小程序后,我必须发送以下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

Is there something wrong with my applet? 我的小程序有问题吗?

In method, private void getKey( APDU apdu , byte[] data) you need to call, 在方法中,您需要调用private void getKey( APDU apdu , byte[] data)

apdu.setIncomingAndReceive();

Remember: 记得:

This is the primary receive method. 这是主要的接收方法。 Calling this method indicates that this APDU has incoming data. 调用此方法表示此APDU具有传入数据。 This method gets as many bytes as will fit without buffer overflow in the APDU buffer following the header. 此方法将获取尽可能多的字节,这些字节将适合头文件后面的APDU缓冲区中没有缓冲区溢出的情况。 It gets all the incoming bytes if they fit. 如果它们适合,它将获取所有传入的字节。

So update your method like this: 因此,像这样更新您的方法:

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);

} }

Note: setIncomingAndReceive method may only be called once in a Applet.process() method. 注意: setIncomingAndReceive方法只能在Applet.process()方法中调用一次。 For more detail, read setIncomingAndReceive . 有关更多详细信息,请阅读setIncomingAndReceive

EDIT: There are several problems in your code. 编辑:您的代码中有几个问题。 I'm mentioning all of them one by one. 我要一一提及。

Problem 1: 问题一:

byte[] Data =new byte[] {(byte) (buffer[ISO7816.OFFSET_CDATA] & 0xFF)};

It creates a byte[] Data of length 1 with value 0x11 . 它创建一个长度为1的byte[] Data ,其值为0x11

Solution: new creates space into persistent EEP memory for Data . 解决方案: new持久性 EEP内存中为Data创建空间。 If you don't need Data again you can make it transient byte array. 如果不再需要Data ,则可以将其设置为transient字节数组。

Rewrite it like this (Persistent): 像这样(持久)重写它:

// it will create a byte array of length of "lc". Content will be `0x00`.
byte[] Data = new byte[(byte) (buffer[ISO7816.OFFSET_LC] & 0xFF)]; 

Or this (Transient): 或此(瞬态):

byte[] Data = JCSystem.makeTransientByteArray((short) (buffer[ISO7816.OFFSET_LC] & 0x00FF), JCSystem.CLEAR_ON_DESELECT);

Problem 2: 问题2:

i) Your generateKey() method will crash, because you are creating byte[] key same as you do for byte[] Data . i)您的generateKey()方法将崩溃,因为您正在创建byte[] key与创建byte[] Data

ii) You may not declare int i because only few cards supports it, use byte or short . ii)您不能声明int i因为只有很少的卡支持int i ,请使用byteshort

Solution: As far as I understand what are you trying to do in the generateKey() method, I rewrite it for you like this: 解决方案:据我了解,您打算在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;
}

The full working code is: 完整的工作代码是:

JavaCard : v.2.2.2 JavaCard :v.2.2.2

globalPlatform : v.2.1.1 globalPlatform :v.2.1.1

Suggestion: Read this document carefully first. 建议:首先请仔细阅读文档。

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;
    }

}

APDU's I sent : 我发送的APDU:

Select Command : 00 A4 04 00 06 A1 A2 A3 A4 A5 00 00 选择命令:00 A4 04 00 06 A1 A2 A3 A4 A5 00 00

Select Command Response : 90 00 选择命令响应:90 00

generateKey Command : 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 generateKey命令: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

generateKey Command Response : 14 27 36 41 50 63 72 8D 9C 15 25 35 45 55 65 75 85 95 B4 B7 B6 B1 B0 B3 90 00 generateKey命令响应:14 27 36 41 50 63 72 8D 9C 15 25 35 45 55 65 75 85 95 B4 B7 B6 B1 B0 B3 90 00

Cheers! 干杯!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM