Как мне прочитать PAN с EMV SmartCard с Java

Мне нужно прочитать номер счета из Maestro / Mastercard с помощью устройства чтения смарт-карт. Я использую Java 1.6 и ее пакет javax.smartcardio. Мне нужно отправить команду APDU, которая запросит у приложения EMV, хранящегося на чипе карты, номер PAN. Проблема в том, что я не могу найти обычный байтовый массив для создания команды APDU, которая будет возвращать необходимые данные где угодно ...

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
10
0
26 095
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Вам нужно создать объект CommandAPDU и передать его команде transfer ().

Вы сможете найти точную команду в документации к вашей смарт-карте, но вот один пример:

byte[] readFile(CardChannel channel) throws CardException {
  CommandAPDU command = new CommandAPDU(0xB0, 0x60, 0x10, 0x00);
  ResponseAPDU response = channel.transmit(command);
  return response.getData();
}

Вы пытались найти в документации значение 0x6D00? Похоже, это может означать, что команда ENVELOPE не поддерживается. Вы пробовали использовать протокол T = 0 вместо T = 1?

Я не ожидал, что мой пример сработает на вашей карте. Я не знаю, какие APDU поддерживает Maestro / MasterCard, поэтому не могу привести рабочий пример.

Попробуйте указать команде явную ожидаемую длину, например:

byte[] readPan(CardChannel channel) throws CardException {
  CommandAPDU command = new CommandAPDU(0x00, 0xB2, 0x5a, 0x14, 250);
  ResponseAPDU response = channel.transmit(command);
  return response.getData();
}
Ответ принят как подходящий

Вам не нужно дополнительно оборачивать APDU. Об этом должен позаботиться уровень API.

Похоже, что ответ 0x6D00 просто означает, что приложение не поддерживает INS.

Сейчас просто устранение неполадок, но вы же начали с выбора приложения MasterCard, верно?

Т.е. что-то вроде этого:

void selectApplication(CardChannel channel) throws CardException {
  byte[] masterCardRid = new byte[]{0xA0, 0x00, 0x00, 0x00, 0x04};
  CommandAPDU command = new CommandAPDU(0x00, 0xA4, 0x04, 0x00, masterCardRid);
  ResponseAPDU response = channel.transmit(command);
  return response.getData();
}

Я не совсем понимаю твой ответ. мой ответ всегда попадает в 0x6D00. что мне делать, если моя карта не поддерживает INS, как вы сказали?

HelmiB 30.10.2012 08:59

вот рабочий пример:

CardChannel channel = card.getBasicChannel(); 

 byte[] selectMaestro = {(byte)0x00, (byte)0xA4,(byte)0x04,(byte)0x00 ,(byte)0x07 ,(byte)0xA0 ,(byte)0x00 ,(byte)0x00 ,(byte)0x00 ,(byte)0x04 ,(byte)0x30 ,(byte)0x60 ,(byte)0x00};
  byte[] getProcessingOptions = {(byte)0x80,(byte)0xA8,(byte)0x00,(byte)0x00,(byte)0x02,(byte)0x83,(byte)0x00,(byte)0x00};
  byte[] readRecord = {(byte)0x00,(byte)0xB2,(byte)0x02,(byte)0x0C,(byte)0x00};

  ResponseAPDU r=null;

   try {
     ATR atr = card.getATR(); //reset kartice

      CommandAPDU capdu=new CommandAPDU( selectMaestro   );

       r=card.getBasicChannel().transmit( capdu );

      capdu=new CommandAPDU(getProcessingOptions);
      r=card.getBasicChannel().transmit( capdu );


      capdu=new CommandAPDU(readRecord);
      r=card.getBasicChannel().transmit( capdu );

Это работает с картой Maestro, я могу прочитать номер PAN, но теперь мне нужно прочитать номер PAN MasterCard. Я не знаю, следует ли мне изменить APDU записи чтения или выбрать APDU приложения. Кто-нибудь знаком с APDU?

Это команда выбора приложения, которую вам нужно изменить. Последняя часть этой команды - это AID приложения, которое вы хотите выбрать. Изменение этого на MasterCard AID должно сработать. Или вы можете просто сократить AID. Если вы поставляете A400000004, ...

Rasmus Faber 05.12.2008 14:08

... он должен соответствовать всем AID, начинающимся с A400000004.

Rasmus Faber 05.12.2008 14:10
atr = open();
prints(atr);

prints("[Step 1] Select 1PAY.SYS.DDF01 to get the PSE directory");
cmd = new ISOSelect(ISOSelect.SELECT_AID, EMV4_1.AID_1PAY_SYS_DDF01);
card_response = execute(cmd);
prints(card_response);
SFI = NumUtil.hex2String((byte)((1 < < 3) | 4));

// try SFI 1 record 1
prints("[Step 2] Send READ RECORD with 0 to find out where the record is");
read = new EMVReadRecord(SFI, "01", "00");
card_response = execute(read);
prints(card_response);
byte_size = NumUtil.hex2String(card_response.getStatusWord().getSw2());

prints("[Step 3] Send READ RECORD with 1C to get the PSE data");
read = new EMVReadRecord(SFI, "01", byte_size);
card_response = execute(read);
prints(card_response);
// the AID is A0000000031010
prints("[Step 4] Now that we know the AID, select the application");

cmd = new ISOSelect(ISOSelect.SELECT_AID, "A0000000031010");
card_response = execute(cmd);
prints(card_response);
prints("[Step 5] Send GET PROCESSING OPTIONS command");

cmd = new EMVGetProcessingOptions();
card_response = execute(cmd);
prints(card_response);

// SFI for the first group of AFL is 0C

prints("[Step 6] Send READ RECORD with 0 to find out where the record is");
read = new EMVReadRecord("0C", "01", "00");
card_response = execute(read);
prints(card_response);
byte_size = NumUtil.hex2String(card_response.getStatusWord().getSw2());

prints("[Step 7] Use READ RECORD with the given number of bytes to retrieve the data");
read = new EMVReadRecord("0C", "01", byte_size);
card_response = execute(read);
prints(card_response);

data = new TLV(card_response.getData());

close();

Привет, Гранди, ты можешь добавить сюда класс TLV?

KCN 19.01.2018 13:16

как насчет использования сканера, получения изображения карты, сканирования содержимого изображения с помощью хорошей библиотеки java ocr (например, http://ocr4j.sourceforge.net/) и поиска (обычно) 16-значной последовательности XXXX-XXXX-XXXX-XXXX, затем вы получите PAN с любой карты EMV, используя java.

Другие вопросы по теме