使用javax.smartcardio从mifare classic中读取块

我想使用Java的javax.smartcardio阅读关于Mifare classic的特定块。 这是我的代码:

public byte[] getCardUID() throws CardException { CardTerminals terminals = TerminalFactory.getDefault().terminals(); terminal = terminals.list().get(0); Card card = terminal.connect("*"); CardChannel channel = card.getBasicChannel(); CommandAPDU command = new CommandAPDU( new byte[] { (byte) 0xFF, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x04, (byte) 0xD4, (byte) 0x4A, (byte) 0x01, (byte) 0x00 }); ResponseAPDU response = channel.transmit(command); card.disconnect(true); if (response.getSW1() == 0x90) { byte[] data = response.getData(); data = Arrays.copyOfRange(data, 0x08, data.length); return data; } return new byte[] {}; } 

这个方法(在互联网上找到的样本)成功读取卡的UID,但是当我尝试构建自己的命令时,我总是变成错误SW1 = 63。

在这个网站(http://www.acs.com.hk/drivers/eng/API_ACR122U_v2.00.pdf)我发现了一些关于APDU的信息,但没有任何工作,我找不到原因。 我没有成功尝试跟随命令(总是错误63):FF B0 00 04 10(B0 – 读取二进制块,04 – 扇区数,10 – 读取16字节)。 我也试过只读一个字节,读取值块(INS B1)但也没有成功。

FF 00 00 00 …(来自我的例子)应该是直接传输,但我不知道以下读取块的指令。

谁能帮我? 非常感谢。 (对不起我的英语不好)

在Mifare Classic 1K标签中有16个扇区,每个扇区包含4个块,每个块包含16个字节。 在从页面读取或写入之前必须使用密钥A或密钥B对扇区进行身份validation。validation完成后,您可以进行读取或写入。 以下是使用该密钥作为密钥A(60)的认证命令认证扇区0:

 FF 86 0000 05 01 0000 60 00 

或者使用该密钥作为密钥B(61)validation扇区0:

 FF 86 0000 05 01 0000 61 00 

或者使用此命令,您还可以validation扇区0

 byte[] authenticationByte = new byte[10]; authenticationByte = new byte[] { (byte) 0xFF, (byte) 0x86, (byte) 0x00, (byte) 0x00, (byte) 0x05, (byte) 0x00,(byte) 0x00, (byte) 0x04, (byte) 0x60,(byte) 0x00 }; 

当身份validation成功时,您将获得90 00.这就是成功消息。 否则响应是63 00,这意味着身份validation失败。 当身份validation完成后,您可以读取块(0,1,2,3),因为扇区0包含4个块,而这些块是块(0,1,2,3)。

使用此命令您可以从扇区0块1读取数据

 byte[] readFromPage = new byte[10]; readFromPage = new byte[] { (byte) 0xFF, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x05, (byte) 0xD4, (byte) 0x40, (byte) 0x00, (byte) 0x30, (byte) 0x01 }; 

最后(字节)0x01是您要读取的块。 在这个答案中,您可以找到完整的代码。 只需用这个替换字节值。 谢谢。