Java Card无需获取数据APDU即可发送数据

时间:2015-07-14 14:12:51

标签: applet javacard

我是这个领域的新手,请原谅我,如果我的问题是天真的。

我想发行一张具有自动选择小程序的Java卡,几乎所有APDU都将在这个小程序中处理。我需要这个applet将数据发送到CAD,而不是使用Java卡标准中的常用格式(即不发送0x61 0xbytesToRead并等待0x00 0xc0)。 例如,我想发送0x23个字节来回答0xA0A40000027F20,这几乎是一个SELECT命令,但是第一个字节错误!

这样可以做到这一点吗?如果有可能请告诉我如何。

感谢。

1 个答案:

答案 0 :(得分:4)

是的,有可能。为了实现目标,您需要执行以下两个步骤:

  1. 您必须选择默认的小程序。
  2. 您必须在接收此命令和/或接收SELECT APDU命令时返回一些数据。
  3. 第一步,回答here

    这取决于卡片 - 并非所有这些卡片似乎都支持在安装后使applet默认设置。但是您可以使用具有--make-default选项的Java的开源GlobalPlatform工具:

    java -jar gp.jar --make-default A000100201100001
    

    IIRC JCOP是实际支持它的卡之一。

    第二步,回答here

    我猜你做“如果选择Applet()然后返回”的“好习惯”?您需要处理传入的APDU而不是简单的返回。 您可以返回数据以选择正常方式,但如果选择成功,请小心返回0x9000。

    必须看起来像这样:

    public void process(APDU apdu)
        { 
           byte[] buf = apdu.getBuffer();
           if (selectingApplet())
              { 
              //send the data in buffer return;
              }
        } 
    

    <强>更新

    在以下答案中回答您的评论:

    我写了以下程序:

    package test;
    
    import javacard.framework.APDU;
    import javacard.framework.ISO7816;
    import javacard.framework.Applet;
    import javacard.framework.ISOException;
    import javacard.framework.Util;
    
    public class Test extends Applet {
    
        public static final byte[] res = { (byte) 0x00, (byte) 0x00, (byte) 0x3B,
                (byte) 0xAD, (byte) 0x3F, (byte) 0x00, (byte) 0x01, (byte) 0x00,
                (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x16,
                (byte) 0xB3, (byte) 0x03, (byte) 0x06, (byte) 0x04, (byte) 0x00,
                (byte) 0x83, (byte) 0x8A, (byte) 0x83, (byte) 0x8A, (byte) 0x00,
                (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x3B, (byte) 0xAD,
                (byte) 0x00, (byte) 0x00, (byte) 0x3B, (byte) 0xAD, (byte) 0x2F,
                (byte) 0x06, (byte) 0x02 };
    
        public static void install(byte[] bArray, short bOffset, byte bLength) {
            new test.Test()
                    .register(bArray, (short) (bOffset + 1), bArray[bOffset]);
        }
    
        public void process(APDU apdu) {
            if (selectingApplet()) {
                return;
            }
    
            byte[] buf = apdu.getBuffer();
    
            if (buf[ISO7816.OFFSET_CLA] == (byte)0xA0 && buf[ISO7816.OFFSET_INS] == (byte) 0xA4 && buf[ISO7816.OFFSET_P1] == (byte) 0x00&& buf[ISO7816.OFFSET_P2] == (byte) 0x00 
                    && buf[ISO7816.OFFSET_LC] == (byte) 0x02 && buf[ISO7816.OFFSET_LC + 1] == (byte) 0x7F  && buf[ISO7816.OFFSET_LC + 2] == (byte) 0x20) {
                ISOException.throwIt((short) 0x9F23);
            } else if (buf[ISO7816.OFFSET_CLA] == (byte) 0xA0 && buf[ISO7816.OFFSET_INS] == (byte) 0xC0  && buf[ISO7816.OFFSET_P1] == (byte) 0x00 
                    && buf[ISO7816.OFFSET_P2] == (byte) 0x00  && buf[ISO7816.OFFSET_P2+1] == (byte) 0x23 ) {
                Util.arrayCopyNonAtomic(res, (short) 0, buf, (short) 0, (short) 35);
                apdu.setOutgoingAndSend((short) 0, (short) 35);
    
            } else {
                ISOException.throwIt((short) 0x9090);
            }
        }
    }
    

    然后我将其安装为默认选择的applet:

    CommandLine> gp -install e:\soq.cap --default
    
    CommandLine>
    

    然后我发送APDU命令:

    CommandLine> OSC.exe -s A0A40000027F20 -s a0c0000023
    Using reader with a card: ACS CCID USB Reader 0
    Sending: A0 A4 00 00 02 7F 20
    Received (SW1=0x9F, SW2=0x23)
    Sending: A0 C0 00 00 23
    Received (SW1=0x90, SW2=0x00):
    00 00 3B AD 3F 00 01 00 00 00 00 00 16 B3 03 06 ..;.?...........
    04 00 83 8A 83 8A 00 03 00 00 3B AD 00 00 3B AD ..........;...;.
    2F 06 02                                        /..
    

    它似乎可以按你的意愿运作。