Pregunta

Necesito leer el número de cuenta de Maestro / Mastercard con lector de tarjetas inteligentes. Estoy usando Java 1.6 y su paquete javax.smartcardio. Necesito enviar un comando APDU que le pedirá a la aplicación EMV almacenada en el chip de la tarjeta el número PAN. El problema es que no puedo encontrar una matriz de bytes regular para construir el comando APDU que devolverá los datos necesarios en cualquier lugar ...

¿Fue útil?

Solución

No debería necesitar envolver más la APDU. La capa API debería ocuparse de eso.

Parece que la respuesta 0x6D00 solo significa que la aplicación no era compatible con el INS.

Solo soluciono problemas ahora, pero comenzaste seleccionando la aplicación MasterCard, ¿verdad?

I.e. algo como esto:

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();
}

Otros consejos

aquí hay un ejemplo de trabajo:

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 );

Esto funciona con la tarjeta Maestro, puedo leer el número PAN, pero ahora necesito leer el número PAN de MasterCard. No sé si debo cambiar la APDU del registro de lectura o seleccionar la APDU de la aplicación. ¿Alguien familiarizado con las APDU?

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();

Necesita construir un objeto CommandAPDU y pasarlo al comando transmit ().

Debería poder encontrar el comando preciso en la documentación de su tarjeta inteligente, pero aquí hay un ejemplo:

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

¿Intentó buscar en su documentación lo que significa 0x6D00? Parece que podría significar que el comando ENVELOPE no es compatible. ¿Has intentado usar el protocolo T = 0 en lugar de T = 1?

No esperaría que mi ejemplo funcione en su tarjeta. No sé qué APDU admite Maestro / MasterCard, por lo que no podría darle un ejemplo de trabajo.

Intenta darle al comando una longitud esperada explícita como esta:

byte[] readPan(CardChannel channel) throws CardException {
  CommandAPDU command = new CommandAPDU(0x00, 0xB2, 0x5a, 0x14, 250);
  ResponseAPDU response = channel.transmit(command);
  return response.getData();
}

¿qué pasa con el uso de un escáner, obtener una imagen de la tarjeta, escanear el contenido de la imagen con una buena biblioteca Java OCR (como http://ocr4j.sourceforge.net/ por ejemplo) y busque una secuencia (generalmente) de 16 dígitos XXXX-XXXX-XXXX-XXXX, luego obtendrá el PAN de cualquier tarjeta EMV usando Java.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top