2008-11-12 45 views
9

? 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 el comando APDU que 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 común para construir el comando APDU que devolverá los datos necesarios en cualquier parte ...¿Cómo leo el PAN de una tarjeta inteligente EMV de Java

Respuesta

6

que no es necesario para envolver la APDU más. La capa API debería encargarse de eso.

Parece que la respuesta 0x6D00 solo significa que la aplicación no admite el INS.

Solución de problemas ahora, pero comenzó 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(); 
} 
+0

No entiendo muy bien tu respuesta. mi respuesta siempre golpea 0x6D00. ¿Qué debo hacer si mi tarjeta no es compatible con INS tal como lo dijo? – HelmiB

0

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

Usted debe ser capaz de encontrar el comando precisa en la documentación de la tarjeta inteligente, pero aquí es un ejemplo:

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

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

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

Trate de dar la orden de una longitud esperada explícita así:

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

es aquí algunos 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 tarjeta Maestro, puedo leer el número PAN, sin embargo, ahora tengo que leer el número PAN de MasterCard. No sé si debería cambiar la APDU de registro de lectura o seleccionar APDU de aplicación. ¿Alguien familiarizado con APDU?

+0

Es el comando de aplicación de selección que necesita cambiar. La última parte de ese comando es el AID de la aplicación que desea seleccionar. Cambiar eso a la AID de MasterCard debería funcionar. O tal vez quiera acortar la AYUDA. Si proporciona A400000004, ... –

+0

... debe coincidir con todos los AID a partir de A400000004. –

1
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

Hola Grandie, ¿Puedes agregar la clase TLV aquí? – KCN

-2

¿qué pasa con el uso de un escáner, para conseguir una imagen de la tarjeta, escanear el contenido de la imagen con una buena biblioteca de Java OCR (como http://ocr4j.sourceforge.net/ por ejemplo) y la búsqueda de una secuencia de dígitos (por lo general) 16 XXXX- XXXX-XXXX-XXXX, entonces obtendrás el PAN de cualquier tarjeta EMV usando java.

Cuestiones relacionadas