首页 文章

如何从智能卡iso7816读取大型二进制数据[重复]

提问于
浏览
1

这个问题在这里已有答案:

import java.io.File;
            import java.io.FileNotFoundException;
            import java.io.FileOutputStream;
            import java.io.IOException;

            import javax.smartcardio.ATR;
            import javax.smartcardio.Card;
            import javax.smartcardio.CardChannel;
            import javax.smartcardio.CardException;
            import javax.smartcardio.CardTerminal;
            import javax.smartcardio.CardTerminals;
            import javax.smartcardio.CommandAPDU;
            import javax.smartcardio.ResponseAPDU;
            import javax.smartcardio.TerminalFactory;

            @SuppressWarnings("restriction")
            public class APDu {


                static FileOutputStream fos = null;

                private static byte[] SELECT   = { 
                                                    (byte) 0x00,    ////CLA
                                                    (byte) 0xA4,    ////INS
                                                    (byte) 0x04,    ////P1
                                                    (byte) 0x00,    ////P2
                                                    (byte) 0x07,    ////Length of AID
                                                    (byte) 0xA0, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x34, (byte) 0x49, (byte) 0x44, (byte) 0x43};

                private static byte[] select_dataSet = {
                                                        (byte) 0x00,    ////CLA
                                                        (byte) 0xA4,    ////INS
                                                        (byte) 0x04,    ////P1
                                                        (byte) 0x00,    ////P2
                                                        (byte) 0x01,    ////Length of AID
                                                        (byte) 0x11 };    ///////////worked

                 private static byte[] read_dataSet   = {
                                                        (byte) 0x00,    ////CLA
                                                        (byte) 0xB0,    ////INS
                                                        (byte) 0x00,    ////P1
                                                        (byte) 0x00,    ////P2   this is the offset
                                                        (byte) 0x00,    ////
                                                        (byte) 0x00,
                                                        (byte) 0xFF
                                                        };  

                 private static CommandAPDU SELECT_APDU = new CommandAPDU(SELECT);
                 private static CommandAPDU select_dataSetAPDU = new CommandAPDU(select_dataSet);
                 private static CommandAPDU read_dataSetAPDU = new CommandAPDU(read_dataSet);


                 private static CardTerminal cardTerminal = null;

                 private static void arrayPrint(byte[] data) {
                      System.out.print("{");
                      arrayPrintBytes(data);
                      System.out.print("} (");
                      arrayPrintHex(data);
                      System.out.print(")");
                 }
                 private static void arrayPrintHex(byte[] data) {
                      StringBuffer sb = new StringBuffer();

                      for (int i = 0; i < data.length; i++) {
                           String bs = Integer.toHexString(data[i] & 0xFF);
                           if (bs.length() == 1)
                                sb.append(0);
                           sb.append(bs).append(" ");
                      }
                      System.out.print( sb.toString() );
                 }
                 private static void arrayPrintBytes(byte[] data) {
                      for(int i=0; i < data.length; i++)
                           System.out.print(data[i]+ " ");
                 }

                 public static boolean sendAPDU(CardChannel ch, CommandAPDU apdu,boolean write) throws CardException {

                      System.out.println("sent these ::: ");arrayPrintHex(apdu.getBytes());
                      ResponseAPDU responseAPDU = ch.transmit(apdu);
                      byte[] response = responseAPDU.getBytes();

                      System.out.print("\n"+responseAPDU.toString()+"  (Nr:"+responseAPDU.getNr() +" SW:"+responseAPDU.getSW()+" SW1:"+responseAPDU.getSW1() +" SW2:"+responseAPDU.getSW2()+")");

                      System.out.print("Bytes received: "); arrayPrint( responseAPDU.getBytes());
                      System.out.print("Data received: ");  arrayPrint( responseAPDU.getData());
                      if(write){

                      }

                      if(write){
                          try {
                              System.out.println("\n\nbytes :::  ");arrayPrintHex(responseAPDU.getData());
                              fos.write(responseAPDU.getData());
                          } catch (FileNotFoundException e) {
                            e.printStackTrace();
                          } catch (IOException e) {
                            e.printStackTrace();
                          }
                      }


                      //Check if response is 0x9000 (code for success)
                      return (response[response.length - 2] == (byte) 0x90 && response[response.length - 1] == (byte) 0x00);
                 }

                 public APDu() {

                 }

                 public static void main(String[] args) throws Exception {
                     File f = new File("dataBytes.dat");

                     fos = new FileOutputStream(f,true);

                     TerminalFactory tf = TerminalFactory.getDefault();
                     CardTerminals ct = tf.terminals();

                     cardTerminal = ct.list().get(0);
                     System.out.println("Selected terminal");

                     if(cardTerminal==null)
                         throw new Exception("ERROR: No cardterminal available to communicate.");
                     try {
                         while (cardTerminal.isCardPresent()) {
                             Card card = null;
                             if ((card = cardTerminal.connect("*")) != null){ 
                                 System.out.println("Connected to card.");
                             } else {
                                 System.out.println("ERROR: Failed to connect to card!"); 
                                 return; 
                             }

                             System.out.print("ATR: "); arrayPrint(((ATR) card.getATR()).getBytes()); System.out.println();

                             CardChannel ch = card.getBasicChannel();

                             //open session
                             if (sendAPDU(ch, SELECT_APDU,false)){
                                 System.out.println("\nReceived data.");
                             } else { 
                                 System.out.println("\nERROR: Unable to get data!"); 
                                 return; 
                             }

                                //select data set
                             if (sendAPDU(ch, select_dataSetAPDU,false)){
                                 System.out.println("\nReceived data.");
                             } else { 
                                 System.out.println("\nERROR: Unable to get data!"); 
                                 return; 
                             }


                             //select read data set
                             if (sendAPDU(ch, read_dataSetAPDU,true)){
                                 System.out.println("\nReceived data.");
                             } else { 
                                 System.out.println("\nERROR: Unable to get data!"); 
                                 return; 
                             }


                             fos.close();
                             return;
                         }
                     } catch (CardException e) {
                         System.out.println("Error isCardPresent()" + e.getCause());
                     }
                 }


            }

http://i.stack.imgur.com/IvQHZ.png

在上面的链接:

左边的数据是我应该从智能卡读取的实际数据,另一边是我从卡上读取的数据 . 我只能读取326字节中的255个字节::::

从00-255数据和2字节状态字

我怎样才能读取剩余的字节 .

================================================== ======================以下是我的代码的输出:

选定的终端连接到卡 . ATR:{59 -1 -107 0 -1 -64 10 49 -2 77 -128 49 -32 107 4 32 5 2 82 85 85 85 85 85 85 -106}(3b ff 95 00 ff c0 0a 31 fe 4d 80 31 e0 6b 04 20 05 02 52 55 55 55 55 55 55 96)

Command ::: 00 a4 04 00 07 a0 00 00 00 34 49 44 43 ---命令打开会话
ResponseAPDU:2个字节,SW = 9000(Nr:0 SW:36864 SW1:144 SW2:0)接收的字节数:{-112 0}(90 00)接收的数据:{}()接收的数据 .

command ::: 00 a4 04 00 01 11 ---命令选择 Headers id:11
ResponseAPDU:25个字节,SW = 9000(Nr:23 SW:36864 SW1:144 SW2:0)接收的字节数:{1 17 6 94 1 70 1 10 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0 - 112 0}(01 11 06 5e 01 46 01 0a 00 00 00 00 00 00 00 0a 00 00 00 00 00 00 00 00 00)收到的数据:{1 17 6 94 1 70 1 10 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0}(01 11 06 5e 01 46 01 0a 00 00 00 00 00 00 00 0a 00 00 00 00 00 00 00)接收数据 .

command ::: 00 b0 00 00 00 00 ff ---命令读取
ResponseAPDU:257字节,SW = 9000(Nr:255 SW:36864 SW1:144 SW2:0)

06 5e是要接收的最大数据,01 46是可用数据 . 我已经阅读了255个字节,我只需要读取剩余的44个字节 . 什么是检索剩余字节的下一个偏移量 .

2 回答

  • -1

    扩展APDU允许以更有效的方式将大量数据发送到卡,进行适当处理并发送回终端 . 无需重新发出多个APDU消息来完成需要大量数据的操作,并要求开发人员对应用程序进行编码以保持跨多个APDU命令的状态,扩展APDU允许applet更有效地执行此功能 . 大型APDU交换 .

    使用this reference获取更多信息 .

    UPDATE:

    在本参考文献中,有一个循序渐进的guid来编写一个利用扩展长度的applet . 请注意,applet应该实现 javacardx.apdu.ExtendedLength 接口 .

    你也可以使用 C0 00 00 XX ,其中XX通常是 SW2 的优惠答案 . 那是因为该卡正在使用 T=0 协议 .

    例如,如果响应是 61 09 ,则发送 00 C0 00 00 09 ,直到响应变为 90 00 . 当然每次你应该用之前的回复替换 XX .

  • 1

    要读取> 255字节的大二进制数据,必须实现链接协议 . 请查看以下链接:

    Reading big file from a javacard applet

    https://community.oracle.com/thread/2207556?tstart=0

相关问题