Reading block from mifare classic using javax.smar

2020-02-06 08:43发布

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)

标签: java mifare
1条回答
来,给爷笑一个
2楼-- · 2020-02-06 09:34

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.

查看更多
登录 后发表回答