问题
I would like to read a specific block on Mifare classic using Java's javax.smartcardio. Here's my code:
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[] {};
}
This method (sample found on internet) successfully reads the UID of the card, but when I try to construct my own command, I always become error SW1=63.
On this site (http://www.acs.com.hk/drivers/eng/API_ACR122U_v2.00.pdf) i have found some informations about APDU, but nothing is working and i cannot find out why. I have tried following command without success (always error 63): FF B0 00 04 10 (B0 - read binary block, 04 - number of sector, 10 - read 16 bytes). I have also tried reading only one byte, reading value block (INS B1) but also no success.
FF 00 00 00 ... (from my example) should be a direct transmit, but i don't know following instructions for reading a block.
Can anyone help me? Thanks a lot. (Sorry for my english)
回答1:
In Mifare Classic 1K tags There are 16 Sectors and each Sectors contains 4 Blocks and each block contains 16 bytes. Before Reading or writing from a page You must have to Authenticate The Sector using Key A or Key B. When Authentication is complete then you can read or write. Here is the Authentication Command Authenticate sector 0 using that key as key A (60):
FF 86 0000 05 01 0000 60 00
Or authenticate sector 0 using that key as key B(61):
FF 86 0000 05 01 0000 61 00
or using this command you can also authenticate sector 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 };
When Authentication is succes then you will get 90 00. That is Success message. Else response is 63 00 , that means authentication failed. When Authentication complete then you can read block (0,1,2,3) cause sector 0 contains 4 block and those are block (0,1,2,3).
Using this command You can read data from Sector 0 block 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 };
Here last (byte) 0x01 is block where you want to read. in this answer you can find the complete code. Just replace the byte value using this. Thanks.
来源:https://stackoverflow.com/questions/12011726/reading-block-from-mifare-classic-using-javax-smartcardio