如何从Java中读取EMV SmartCard中的PAN

我需要使用智能卡读卡器读取Maestro / Mastercard的帐号。 我正在使用Java 1.6及其javax.smartcardio包。 我需要发送APDU命令,它会询问存储在卡芯片上的EMV应用程序的PAN号。 问题是,我找不到常规的字节数组来构造APDU命令,它会在任何地方返回所需的数据……

您不应该进一步包装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(); } 

这是一些工作示例:

 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编号,但现在我需要读取MasterCard的PAN编号。 我不知道应该更改读取记录APDU还是选择应用程序APDU。 有熟悉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(); 

您需要构造一个CommandAPDU对象并将其传递给transmit() – 命令。

您应该能够在智能卡的文档中找到精确的命令,但这是一个示例:

 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?

我不希望我的例子在你的卡上工作。 我不知道Maestro / MasterCard支持哪些APDU,所以我不能给你一个有效的例子。

尝试给命令一个明确的预期长度,如下所示:

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

怎么样使用扫描仪,获取卡片的图片,用一个好的java ocr库扫描图片的内容(例如http://ocr4j.sourceforge.net/ )并搜索(通常)16位数序列XXXX-XXXX-XXXX-XXXX,然后您将使用java从任何EMV卡获取PAN。

Interesting Posts