如何将两步卡响应改为一步?

时间:2016-06-08 07:28:02

标签: smartcard javacard smartcard-reader pcsc

我正在使用Java Card开发一个程序。 有时当我向卡发送命令时,它响应为“0X61 0Xxx”,这意味着存在一个0Xxx长度的响应,我应该回答得到它。

我的问题是,我怎样才能避免这种反应并立即得到答案?

提前致谢

1 个答案:

答案 0 :(得分:4)

这取决于!

有时您会收到61XX,因为您正在与这样编写的小程序进行通信!我的意思是applet的编写方式是使用GET RESPONSE APDU命令返回其数据。因此,在这种情况下,除了请求applet开发人员根据需要修改applet之外,您无法执行任何操作。

但有时它并不是如上所述返回数据的applet,但它是智能卡。实际上T=0智能卡会返回数据。因此,您只需将智能卡更改为支持T=1通信协议的较新卡。在这种情况下,您有一个小程序CAP文件,当您在T=0卡上安装时,它会分两步返回数据,当您在T=1智能卡上安装它时,它会在一步中返回数据。

假设您编写了如下程序。它有四个不同的APDU命令(INS = 00, 01, 02, 03),用于将temp字节数组内容返回给用户:

package soq;

import javacard.framework.*;

public class SOQ extends Applet
{
    byte[] temp = {(byte)'T',(byte)'h',(byte)'i',(byte)'s',
                   (byte)'-',(byte)'I',(byte)'s',(byte)'-',
                   (byte)'A',(byte)'-',(byte)'T',(byte)'e',(byte)'s',(byte)'t'};

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

    public void process(APDU apdu)
    {
        if (selectingApplet())
        {
            return;
        }

        byte[] buf = apdu.getBuffer();
        short le;

        switch (buf[ISO7816.OFFSET_INS])
        {
        case (byte)0x00:
            apdu.setOutgoing();
            apdu.setOutgoingLength((short)14);
            apdu.sendBytesLong(temp, (short)0, (short)14);
            break;

        case (byte) 0x01:
            Util.arrayCopyNonAtomic(temp, (short)0, buf, (short)0, (short)14);
            apdu.setOutgoingAndSend((short)0, (short)14);
            break;

        case (byte) 0x02:
            le = apdu.setOutgoing();
            if (le != (short)0x000E){
                ISOException.throwIt((short)0x6C0E);
            }else{
                Util.arrayCopyNonAtomic(temp, (short)0, buf, (short)0, (short)14);
                apdu.setOutgoingLength((short)le);
                apdu.sendBytes((short)0, le);
            }
            break;

        case (byte) 0x03:
            le = apdu.setOutgoing();
            if (le != (short)0x000E){
                ISOException.throwIt((short)0x6C0E);
            }else{
                apdu.setOutgoingLength((short)14);
                apdu.sendBytesLong(temp, (short)0, le);
            }
            break;
        default:
            ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
    }

}

当它安装在与 T=1 协议上的用户通信的卡上时,您有:

Select Applet begin...
Select Applet successful.

Send: 00 00 00 00 00
Recv: 54 68 69 73 2D 49 73 2D 41 2D 54 65 73 74 90 00

Send: 00 01 00 00 00
Recv: 54 68 69 73 2D 49 73 2D 41 2D 54 65 73 74 90 00

Send: 00 02 00 00 00
Recv: 6C 0E
Send: 00 02 00 00 0E
Recv: 54 68 69 73 2D 49 73 2D 41 2D 54 65 73 74 90 00

Send: 00 03 00 00 00
Recv: 6C 0E
Send: 00 03 00 00 0E
Recv: 54 68 69 73 2D 49 73 2D 41 2D 54 65 73 74 90 00

当它安装在通过 T=0 协议与用户通信的卡上时,您就拥有:

Select Applet begin...
Select Applet successful.

Send: 00 00 00 00 00
Recv: 6C 0E
Send: 00 00 00 00 0E
Recv: 54 68 69 73 2D 49 73 2D 41 2D 54 65 73 74 90 00

Send: 00 01 00 00 00
Recv: 6C 0E
Send: 00 01 00 00 0E
Recv: 54 68 69 73 2D 49 73 2D 41 2D 54 65 73 74 90 00

Send: 00 02 00 00 00
Recv: 6C 0E
Send: 00 02 00 00 0E
Recv: 54 68 69 73 2D 49 73 2D 41 2D 54 65 73 74 90 00

Send: 00 03 00 00 00
Recv: 6C 0E
Send: 00 03 00 00 0E
Recv: 54 68 69 73 2D 49 73 2D 41 2D 54 65 73 74 90 00

如上所示,在两种情况下,INS=0x2 or 0x03Le=0x00的APDU命令都会返回0x6C0E。这是因为applet是这样编写的。但是对于INS=0x00 or 0x01,返回值取决于通信协议。对于T=1,他们会返回0x6C0E,而对于T=1,他们会返回数据。