How to read a MiFARE Classic tag

To read a MiFARE Classic sector please follow the steps below:

  • The first step is to read-up on the NFC Basics on the Android developer website, and set up the access to the device’s NFC hardware to properly handle NFC intents.
  • Use an NFC tag to trigger the application
  • Wait for a NfcAdapter.ACTION_TECH_DISCOVERED intent, and recover the MifareClassic object through the Tag object.
/**
  * Treat NfcAdapter.ACTION_TECH_DISCOVERED incoming intents and start the tag 
  * reading.
  *
  * @param intent
  */
private void resolveIntent(Intent intent) {
    if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) {

        /* Get Tag object from intent */
        Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        /* Recover the MifareClassic object from the Tag object */
        MifareClassic tag = MifareClassic.get(tagFromIntent) ;
    }
}
  • Connect to the tag
/* Connection to the tag */
tag.connect();
  • Get general information which will be useful for the tag reading
/* Get general information */
sectorCount = tag.getSectorCount(); // Get the number of sectors for this tag
tagSize = tag.getSize(); // Get the tag size
  • To read a sector of a MiFARE Classic tag, the sector needs to be authenticated. To operate the authentication, keys are used. The following method will initialize the key(s). (A list of common keys is available at the end of this page)
/* Create the defaultKeys array */
List<byte[]> defaultKeys = new ArrayList<byte[]>();

/* Add a key to the array */
defaultKeys.add(MifareClassic.KEY_DEFAULT);
  • Try to authenticate a sector. It returns false if the authentication failed, true otherwise. If it fails, try with other keys.
/* Authenticate the sector number « secId » with the key « keyUsed » */
auth = tag.authenticateSectorWithKeyA(secId, keyUsed);
auth = tag.authenticateSectorWithKeyB(secId, keyUsed);
  • When the authentication is successful, before reading the sector, get the number of blocks for this sector.
/* Get the number of blocks for the sector « secId » */
tag.getBlockCountInSector(secId)
  • Then read a block from the authenticated sector
/* Read the block number « blkId » */
Byte[] data = tag.readBlock(blkId);

Notes :

  • Each sector can have a different number of blocks

  • Common known keys :

    0x00 0x00 0x00 0x00 0x00 0x00
    0xA0 0xB0 0xC0 0xD0 0xE0 0xF0
    0xA1 0xB1 0xC1 0xD1 0xE1 0xF1
    0xB0 0xB1 0xB2 0xB3 0xB4 0xB5
    0xAA 0xBB 0xCC 0xDD 0xEE 0xFF