Como leio o PAN a partir de uma SmartCard EMV de Java
Pergunta
Eu preciso ler o número da conta do Maestro / Mastercard com leitor de cartão inteligente. Eu estou usando Java 1.6 e seu pacote javax.smartcardio. Eu preciso enviar comando APDU que irá pedir a aplicação EMV armazenados no chip do cartão para o número PAN. O problema é que não consigo encontrar array de bytes regular para construir comando APDU que irá retornar os dados necessários em qualquer lugar ...
Solução
Você não deve precisar para embrulhar o APDU ainda mais. A camada API deve tomar cuidado com isso.
Parece que a resposta 0x6D00 apenas significa que a aplicação não suportam o INS.
Apenas solução de problemas agora, mas você se começar por selecionar a aplicação MasterCard, certo?
i. algo como isto:
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();
}
Outras dicas
aqui é algum exemplo de trabalho:
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 );
Isso funciona com cartão Maestro, eu posso ler número PAN, mas agora eu preciso ler número PAN da MasterCard. Eu não sei o que eu deveria mudar o registro de leitura APDU ou selecione APDU aplicação. Qualquer pessoa familiarizada com APDUs?
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();
Você precisa fazer construir um objeto CommandAPDU e passá-lo para a transmissão (.) - comando
Você deve ser capaz de encontrar o comando precisa na documentação para o seu smartcard, mas aqui está um exemplo:
byte[] readFile(CardChannel channel) throws CardException {
CommandAPDU command = new CommandAPDU(0xB0, 0x60, 0x10, 0x00);
ResponseAPDU response = channel.transmit(command);
return response.getData();
}
Você tentou olhando para cima na documentação que significa 0x6D00? Parece que isso pode significar que o comando ENVELOPE não é suportado. Você já tentou usar protocolo T = 0 em vez de T = 1?
Eu não esperaria que o meu exemplo para o trabalho em seu cartão. Eu não sei qual APDUs os MasterCard-suportes Maestro /, então eu não poderia dar-lhe um exemplo de trabalho.
Tente dar o comando de uma duração prevista 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();
}
que sobre usando um scanner, obter uma imagem do cartão, a digitalização do conteúdo da imagem com uma biblioteca boa java ocr (como http://ocr4j.sourceforge.net/ por exemplo) e procurar por um (normalmente) seqüência de 16 dígitos XXXX-XXXX-XXXX-XXXX, então você vai ter o PAN a partir de qualquer cartão EMV usando java.