Как мне прочитать PAN с карты EMV SmartCard из Java? - PullRequest
9 голосов
/ 12 ноября 2008

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

Ответы [ 6 ]

6 голосов
/ 13 ноября 2008

Вам не нужно оборачивать 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();
}
4 голосов
/ 20 ноября 2008

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

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?

1 голос
/ 17 февраля 2009
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();
0 голосов
/ 08 августа 2014

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

0 голосов
/ 12 ноября 2008

Вы пытались найти в своей документации, что означает 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();
}
0 голосов
/ 12 ноября 2008

Вам необходимо создать объект CommandAPDU и передать его команде trans () -.

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

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