4

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)

  • You are in fact using an ACR122U, right? – martijno Aug 17 '12 at 20:48
  • Yes, I'm not 100% sure because i havent installed this driver, but i think I'm using acr122u. Btw. my reader is touchatag. –  Aug 18 '12 at 08:55
  • Ok, as far as I know you should be able to use these proprietary APDUs to talk to your mifare, so you should in principle be able to do this using `javax.smartcardio`. Maybe the traffic is going to the internal SAM smart card instead of to the mifare card? If you open your reader, does it contain a contact smart card? – martijno Aug 18 '12 at 14:50
  • I thought, that it should be possible because of succesfull UID reading. I cannot see any screwdrivers on my reader and honestly I would rather leave my reader unopened. I tried to find some technical details, but no success. Theoretically, if the redaer has a internal SAM smart card, what does it mean and what is the difference in the communication? –  Aug 18 '12 at 16:46
  • So, i have found out, that in my reader is a contact smart card that looks like a SIM card in mobile phone. –  Aug 18 '12 at 18:48
  • When i'm trying this code: `CardTerminals terminals = TerminalFactory.getDefault().terminals(); CardTerminal terminal = terminals.list().get(0); terminal.waitForCardPresent(0); System.out.println("Card present..."); terminal.waitForCardAbsent(0); System.out.println("Card absent..."); Thread.currentThread().sleep(3000);` method prints "Card present...", but it remain standing on waitForCardAbsent(). Means this, that my program detects internal card? If yes, wouldit be possible to detect somehow presence of mifare cards? –  Aug 18 '12 at 19:16
  • We've dealt with Touchatag (or Tikitag as it was called back then) enternal/external card in the context of a different project by wrapping some of the ACR specific commands in a `javax.smartcardio` provider. See http://scuba.svn.sourceforge.net/viewvc/scuba/acr122provider/src/net/sourceforge/scuba/smartcards/ACR122TerminalFactorySpi.java?revision=181&view=markup. – martijno Aug 19 '12 at 19:24
  • Thank you a lot! You were right, the whole communication went to internal card. For communication with contactless card was needed command for direct transmit (FF 00 00 00). All is described in this document http://www.idvation.com/uploads/media/API_ACR122-SAM_33.pdf –  Aug 20 '12 at 15:57
  • Hi...anyone has an example to read and write Mifare cards with java. thank if I can help. – Marco R Jan 07 '15 at 13:57

1 Answers1

7

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.

Community
  • 1
  • 1
Md. Sajedul Karim
  • 6,749
  • 3
  • 61
  • 87