Reading a block from mifare classic with javax.smartcardio

I would like to read a specific block on the Mifare classic using Java javax.smartcardio. Here is 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 (a sample found on the Internet) successfully reads the UID of the card, but when I try to create my own team, I always get the error SW1 = 63.

On this site (http://www.acs.com.hk/drivers/eng/API_ACR122U_v2.00.pdf) I found information about APDU but nothing works and I canโ€™t understand why. I tried the following command without success (always error 63): FF B0 00 04 10 (B0 - read binary block, 04 - number of sectors, 10 - read 16 bytes). I also tried reading only one byte while reading the value block (INS B1), but also failed.

FF 00 00 00 ... (from my example) there should be a direct transfer, but I do not know the following instructions for reading a block.

Can anyone help me? Thank you very much. (Sorry for my English)

+4
source share
1 answer

There are 16 sectors in the Mifare Classic 1K tags, and each sector contains 4 blocks, and each block contains 16 bytes. Before reading or writing from the page, you must authenticate the sector using the A key or the B key. When authentication is complete, you can read or write. Here is the authentication command Authenticate sector 0 using this key as the A key (60):

 FF 86 0000 05 01 0000 60 00 

Or authenticate sector 0 using this 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 the authentication is successful, you will receive 90 00. This is a success message. Else answer 63 00, this means that authentication failed. When authentication is complete, you can read the block (0,1,2,3) calling sector 0 containing 4 blocks and they are blocks (0,1,2,3).

Using this command you can read data from block 0 of sector 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 the last (byte) 0x01 is the block you want to read. in this answer you can find the full code. Just replace the byte value using this. Thanks.

+6
source

All Articles