首页 文章

如何将数据数组发送到我的Applet并通过Applet进行操作并在响应apdu中返回新数据?

提问于
浏览
0

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


我想将一个随机字节数组(包括例如24个元素)发送到我的JavaCard applet,然后我的applet应该使用特定方法更改该数组 . 例如,该方法使用 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;
    }

}

我必须在编译并选择我的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

我的小程序有问题吗?

1 回答

  • 1

    在方法中, private 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()方法中调用一次 . 有关更多详细信息,请阅读setIncomingAndReceive .

    EDIT: 您的代码中存在多个问题 . 我一个接一个地提到它们 .

    Problem 1:

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

    它创建一个长度为1的 byte[] Data ,其值为 0x11 .

    Solution: newDatapersistent EEP内存创建空间 . 如果您不再需要 Data ,则可以将其设为 transient 字节数组 .

    像这样重写它(持久):

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

    或者这个(瞬态):

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

    Problem 2:

    i)你的 generateKey() 方法会崩溃,因为你创建的 byte[] keybyte[] Data 相同 .

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

    Solution: 据我所知,您在 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;
    }
    

    完整的工作代码是:

    JavaCard :v.2.2.2

    globalPlatform :v.2.1.1

    Suggestion: 首先仔细阅读this文件 .

    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:

    选择命令:00 A4 04 00 06 A1 A2 A3 A4 A5 00 00选择命令响应:90 00 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命令响应: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

    干杯!

相关问题