Reading block from mifare classic using javax.smartcardio

13,128

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.

Share:
13,128

Related videos on Youtube

Admin
Author by

Admin

Updated on June 04, 2022

Comments

  • Admin
    Admin about 2 years

    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)