使用SCL010获取Mifare Ultralight的UID

我想获得Mifare Ultralight NFC标签的UID。 在Java中我有这个代码:

TerminalFactory factory = TerminalFactory.getDefault(); List terminals = factory.terminals().list(); System.out.println("Terminals: " + terminals); CardTerminal terminal = terminals.get(0); Card card = terminal.connect("*"); System.out.println("card: " + card); CardChannel channel = card.getBasicChannel(); ResponseAPDU answer = channel.transmit(new CommandAPDU(0xFF, 0xCA, 0x00, 0x00, 0x00)); byte[] uid = answer.getBytes(); 

问题是我收到两个字节而不是UID。 有什么问题? APDU是否正确?

您实际使用的命令不是您所期望的。

使用此阅读器获取UID /序列号/枚举标识符的正确命令APDU是:

 +------+------+------+------+------+ | CLA | INS | P1 | P2 | Le | +------+------+------+------+------+ | 0xFF | 0xCA | 0x00 | 0x00 | 0x00 | +------+------+------+------+------+ 

但是,您使用的构造函数定义为:

 public CommandAPDU(int cla, int ins, int p1, int p2, int ne); 

所以

 new CommandAPDU(0xFF, 0xCA, 0x00, 0x00, 0x00) 

您正在创建具有以下参数的C-APDU: CLA = 0xFFINS = 0xCAP1 = 0x00P2 = 0x00 。 到目前为止,这与上面的APDU相同。 但最后一个参数是Ne = 0x00Ne = 0表示预期响应字节数为零(而Le = 0表示预期响应字节数为(最多)256)。

这样可以有效地创建以下Case-1 APDU:

 +------+------+------+------+ | CLA | INS | P1 | P2 | +------+------+------+------+ | 0xFF | 0xCA | 0x00 | 0x00 | +------+------+------+------+ 

因此,最多您将获得2字节状态字作为响应(指示成功使用0x90 0x00或指示错误,状态代码如0x6X 0xXX )。

所以你可以使用字节数组来形成你的APDU:

 new CommandAPDU(new byte[] { (byte)0xFF, (byte)0xCA, (byte)0x00, (byte)0x00, (byte)0x00 } ) 

或者您可以为Ne指定适当的值:

 new CommandAPDU(0xFF, 0xCA, 0x00, 0x00, 256) 
 import java.nio.ByteBuffer; import java.util.List; import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; import javax.smartcardio.CardTerminal; import javax.smartcardio.TerminalFactory; public class Read { public Read() { try { CardTerminal terminal = null; // show the list of available terminals TerminalFactory factory = TerminalFactory.getDefault(); List terminals = factory.terminals().list(); String readerName = ""; for (int i = 0; i < terminals.size(); i++) { readerName = terminals.get(i).toString() .substring(terminals.get(i).toString().length() - 2); //terminal = terminals.get(i); if (readerName.equalsIgnoreCase(" 0")) { terminal = terminals.get(i); } } // Establish a connection with the card System.out.println("Waiting for a card.."); if(terminal==null) return; terminal.waitForCardPresent(0); Card card = terminal.connect("T=0"); CardChannel channel = card.getBasicChannel(); // Start with something simple, read UID, kinda like Hello World! byte[] baReadUID = new byte[5]; baReadUID = new byte[] { (byte) 0xFF, (byte) 0xCA, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; System.out.println("UID: " + send(baReadUID, channel)); // If successfull, the output will end with 9000 // OK, now, the real work } catch (Exception ex) { ex.printStackTrace(); } } public String send(byte[] cmd, CardChannel channel) { String res = ""; byte[] baResp = new byte[258]; ByteBuffer bufCmd = ByteBuffer.wrap(cmd); ByteBuffer bufResp = ByteBuffer.wrap(baResp); // output = The length of the received response APDU int output = 0; try { output = channel.transmit(bufCmd, bufResp); }` catch (CardException ex) { ex.printStackTrace(); }` for (int i = 0; i < output; i++) { res += String.format("%02X", baResp[i]); // The result is formatted as a hexadecimal integer } return res; } public static void main(String[] args) { new Read(); } } 

读取此代码后,为了读写目的,请使用波纹管命令。

并阅读从页面:04到页面:07命令是:

 read_four_to_seven = new byte[]{(byte) 0xFF, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x05, (byte) 0x0D4, (byte) 0x40, (byte) 0x01, (byte) 0x30, (byte) 0x04, (byte) 0x07 }; System.out.println("Read : " + send(read_four_to_seven, channel)); 

写入第04页:

 Write_Page_Four = new byte[] { (byte) 0xFF, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x15, (byte) 0xD4, (byte) 0x40, (byte) 0x01, (byte) 0xA0, (byte) 0x04, (byte) 0x4D, (byte) 0x65, (byte) 0x73, (byte) 0x75, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; System.out.println("Read : " + send(Write_Page_Four, channel));