Инициировать обновление с учетом 6985 и 61xx в двух разных сценариях

У меня есть java-карта, и я пишу небольшой код для отправки APDU на java-карту. здесь, когда я отправляю команду Init_Update, m получает 0x6985, например: -

CMD -> 80 50 00 00 08 11 22 33 44 55 66 77 88
RES <- 6985

Но когда я отправляю эту команду с другим инструментом, она дает требуемый результат: -

Transmit: 80 50 00 00 08    []
  11 22 33 44 55 66 77 88                            ."3DUfw.
Card answered: 61 1C

Мой код Java работает хорошо для другой java-карты, которую у меня есть. Может ли кто-нибудь сказать мне, что может быть причиной этого другого поведения.

// full java code


     public static void main(String[] args) {
            // TODO code application logic here
            try
            {

        factory = TerminalFactory.getDefault();
                    terminals = factory.terminals().list(); 
                terminal = terminals.get(0);
                card = terminal.connect("*");
                    channel =card.getBasicChannel();

                    CommandAPDU cmdAPDU;
                     ResponseAPDU response;
                    byte[] select_isd = {(byte) 0x00,(byte) 0xA4,(byte) 0x04,(byte) 0x00,(byte) 0x08,(byte) 0xA0,(byte) 0x00,
                                         (byte) 0x00,(byte) 0x00,(byte) 0x03,(byte) 0x00,(byte) 0x00,(byte) 0x00 };
                    cmdAPDU = new CommandAPDU(select_isd);
                     response = channel.transmit(cmdAPDU);
                    byte[] INIT_UPDATE = {(byte) 0x80,(byte) 0x50,(byte) 0x00,(byte) 0x00,(byte) 0x08,(byte) 0x11,(byte) 0x22,
                                          (byte) 0x33,(byte) 0x44,(byte) 0x55,(byte) 0x66,(byte) 0x77,(byte) 0x88 };
                     cmdAPDU = new CommandAPDU(INIT_UPDATE);
                     response = channel.transmit(cmdAPDU);
 }
        catch( Exception ex)
        {

        }
    }

Другой журнал инструментов выглядит так: -

Card opened
12 bytes ATR received:
3B 68 00 00 00 73 C8 40 00 00 90 00

Transmit: 00 A4 04 00 08    [SELECT FILE]
  A0 00 00 00 03 00 00 00                            ........
Card answered: 61 12

Transmit: 00 C0 00 00 12    [GET RESPONSE]
Card answered: 90 00
  6F 10 84 08 A0 00 00 00 03 00 00 00 A5 04 9F 65    o..............e
  01 FF                                              ..

Transmit: 80 50 00 00 08    []
  11 22 33 44 55 66 77 88                            ."3DUfw.
Card answered: 61 1C

Но когда я запускаю свой Java-код, я получаю команду 6985 для команды INIT_UPDATE.

Пожалуйста, дайте мне знать, если потребуется какая-либо другая информация для моей стороны.

== вновь добавлено === Я попытался запустить мой script в оболочке JCOP, мой script выглядит так: -

/mode trace=on
/terminal 
/atr
/send 80CAA08D05
/send 802E000014B555C94B0B2368B4840201808502032288020060
/send 80D8000000
/atr
/send 80500000081122334455667788

и он дает мне требуемый результат. То же самое я пытался реализовать в java, мой новый код Java выглядит так: ===== Новый обновленный код JAVA ===

factory = TerminalFactory.getDefault();
         terminals = factory.terminals().list(); 
         terminal = terminals.get(0);

         card = terminal.connect("*");
         channel =card.getBasicChannel();

         CommandAPDU cmdAPDU;
         ResponseAPDU response;
         byte[] x = { (byte) 0x80, (byte) 0xCA, (byte) 0xA0,(byte) 0x8D,(byte)0x05};
         byte[] y = {    remove command for security reasons};
         byte[] z = {     (byte) 0x80, (byte) 0xD8, (byte) 0x00, (byte) 0x00, (byte) 0x00}; // it set default key


           cmdAPDU = new CommandAPDU(x);
         response = channel.transmit(cmdAPDU);
                System.out.println(response.toString());

                  cmdAPDU = new CommandAPDU(y);
         response = channel.transmit(cmdAPDU);
                System.out.println(response.toString());

                           cmdAPDU = new CommandAPDU(z);
         response = channel.transmit(cmdAPDU);
                System.out.println(response.toString());

                   card.disconnect(true);
                    card = terminal.connect("*");
                   channel =card.getBasicChannel();


         byte[] INIT_UPDATE = {(byte) 0x80,(byte) 0x50,(byte) 0x00,(byte) 0x00,(byte) 0x08,(byte) 0x11,(byte) 0x22,(byte) 0x33,(byte) 0x44,(byte) 0x55,(byte) 0x66,(byte) 0x77,(byte) 0x88 };

         cmdAPDU = new CommandAPDU(INIT_UPDATE);
        response = channel.transmit(cmdAPDU);

Ответ 1

6985 означает, что условия использования не выполнены. Поскольку вы до сих пор не использовали какие-либо ключи, это, вероятно, означает, что карта заблокирована или завершена.


611C - это слово состояния, используемое для отправки APDU по T = 0. T = 0 не обрабатывает как команду, так и ответ (аналогично "случаю ISO 4" ) в том же APDU, поэтому для команд ISO 4 требуется значение GET RESPONSE. Либо первое приложение обрабатывает это с глаз долой (как это делает сама Java-карта) - объединение двух APDU - или создает соединение T = 1 вместо соединения T = 0.

Это не имеет никакого отношения к слову состояния 6985, потому что вы ожидаете, что это предупреждение будет создано до того, как будет обработана бизнес-логика команды INITIALIZE UPDATE - команда обрабатывается только в том случае, если вывод может быть произведен.

Ответ 2

  • Для SW '6985'

В соответствии со спецификацией Руководство по отображению существующего GP v2.1.1 Реализация на v2.2.1: в разделе 6.5.2

"Если защищенный канал в настоящее время активен на логическом канале, отличном от логического канала, на котором была выведена эта команда (команда" Инициализировать обновление "), возвращается ответ" 6985 ".

Просьба перекрестно проверить это поведение в случае, если команда "Инициализировать обновление" завершилась неудачей с помощью 6985.

  1. Для SW '611C'

Если информация слишком длинна для поля данных с одним ответом, тогда карта должна вернуть начало информации, за которой следует SW1-SW2, установленный в "61XX". Затем последующий GET RESPONSE предоставляет "XX" байты информации. Процесс может повторяться до тех пор, пока карта не отправит SW1-SW2 в значение "9000".

Здесь в этом случае вам нужно отправить команду GET RESPONSE с P3 как 1C, а CARD вернет 1C байтов данных.

Ответ 3

Вы можете использовать BusHound для захвата некоторых APDU, а затем сравнить и проанализировать различия между двумя инструментами во время отправки команд.

Ответ 4

Могу ли я попросить вас попробовать эту программу?

 public static void main(String[] args) {
     try{
         factory = TerminalFactory.getDefault();
         terminals = factory.terminals().list(); 
         terminal = terminals.get(0);

         card = terminal.connect("*");
         channel =card.getBasicChannel();

         CommandAPDU cmdAPDU1;
         CommandAPDU cmdAPDU2;
         ResponseAPDU response1;
         ResponseAPDU response2;

         byte[] select_isd = {(byte) 0x00,(byte) 0xA4,(byte) 0x04,(byte) 0x00,(byte) 0x08,(byte) 0xA0,(byte) 0x00,(byte) 0x00,(byte) 0x00,(byte) 0x03,(byte) 0x00,(byte) 0x00,(byte) 0x00 };
         byte[] INIT_UPDATE = {(byte) 0x80,(byte) 0x50,(byte) 0x00,(byte) 0x00,(byte) 0x08,(byte) 0x11,(byte) 0x22,(byte) 0x33,(byte) 0x44,(byte) 0x55,(byte) 0x66,(byte) 0x77,(byte) 0x88 };

         cmdAPDU1 = new CommandAPDU(select_isd);
         cmdAPDU2 = new CommandAPDU(INIT_UPDATE);
         response1 = channel.transmit(cmdAPDU1);
         response2 = channel.transmit(cmdAPDU2);
         }
     catch( Exception ex)
     {

     }
}

Я боюсь, если new CommandAPDU между transmit методами, reset соединение между картой и читателем.

Update:

Если вышеуказанная программа возвращает ту же ошибку, попробуйте также:

public static void main(String[] args) {
     try{
         factory = TerminalFactory.getDefault();
         terminals = factory.terminals().list(); 
         terminal = terminals.get(0);

         card = terminal.connect("*");
         channel =card.getBasicChannel();

         CommandAPDU cmdAPDU;
         ResponseAPDU response;


         byte[] select_isd = {(byte) 0x00,(byte) 0xA4,(byte) 0x04,(byte) 0x00,(byte) 0x08,(byte) 0xA0,(byte) 0x00,(byte) 0x00,(byte) 0x00,(byte) 0x03,(byte) 0x00,(byte) 0x00,(byte) 0x00 };
         byte[] get_response={(byte)0x00,(byte)0xC0 ,(byte)0x00 ,(byte)0x00 ,(byte)0x12};
         byte[] INIT_UPDATE = {(byte) 0x80,(byte) 0x50,(byte) 0x00,(byte) 0x00,(byte) 0x08,(byte) 0x11,(byte) 0x22,(byte) 0x33,(byte) 0x44,(byte) 0x55,(byte) 0x66,(byte) 0x77,(byte) 0x88 };

         cmdAPDU = new CommandAPDU(select_isd);
         response = channel.transmit(cmdAPDU);

         cmdAPDU = new CommandAPDU(get_response);
         response = channel.transmit(cmdAPDU);

         cmdAPDU = new CommandAPDU(INIT_UPDATE);
         response = channel.transmit(cmdAPDU);

         }
     catch( Exception ex)
     {

     }
}

С нетерпением жду вашего ответа.

Update-2:

Я думаю, что попробовать Python script полезно узнать, в чем проблема. Вы также можете попробовать:

>>> from smartcard.System import readers
>>> from smartcard.util import toHexString
>>>
>>> r=readers()
#if you have more than one reader or a dual interface reader, put the right index in the below line instead of `0`
>>> connection = r[0].createConnection()
>>> connection.connect()
>>>
>>> SELECT = [0xA0, 0xA4, 0x04, 0x00, 0x08 , 0xA0 , 0x00 , 0x00 , 0x00 , 0x03 , 0x00 , 0x00 , 0x00 ]
>>> GET_RESPONSE = [ 0x00, 0xC0, 0x00, 0x00, 0x12]
>>> INIT_UPDATE= [0x80, 0x50, 0x00, 0x00, 0x08, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]
>>>
>>> data, sw1, sw2 = connection.transmit( SELECT)
>>> print "%s %x %x" % (data, sw1, sw2)
>>>
#if the sw1 and sw2 of above command is not `0x6112`, don't send GET_RESPOSE command.
>>> data, sw1, sw2 = connection.transmit( GET_RESPONSE)
>>> print "%s %x %x" % (data, sw1, sw2)    
>>>
>>> data, sw1, sw2 = connection.transmit( INIT_UPDATE)
>>> print "%s %x %x" % (data, sw1, sw2)

Обратите внимание, что приведенный выше script для Python 2.7, и вы должны istall PySCard также