Search code examples
androidauthenticationnfcmifarendef

Write to NTAG216 after authenticating?


I am authenticating my tag using this piece of code

nfcA.connect();
byte[] authResponse = nfcA.transceive(new byte[]{
                (byte)0x1b,
                pwd[0], pwd[1], pwd[2], pwd[3]
        });
nfcA.close();

I checked the result of authResponse and it is equal to my pack. After authenticating, I write NDEF contents using the writeNdefMessage() method of the Ndef class, but I was not able to write.

This is where I found the way to authenticate the tag.

This is my approach:

  • Authenticate tag (using that piece of code)
  • If response of authentication is equal to my pack, proceed to writing the NDEF message

However, I get a java.io.IOException whenever I'm calling writeNdefMessage().


Solution

  • The reason why you can't write is because you lose authentication state again before actually writing to the tag. With most devices (though some exceptions to this exist!), calling tag.connect()/tag.close() will cause the tag to be re-activated and, consequently, to lose its authentication state. Thus, you need to authenticate and write within the same connection.

    As you can't send low-level commands through the Ndef abstraction, this means that you have to do all the writing with low-level commands. I.e. you have to re-implement the NDEF abstraction layer for that particular tag type (the NFC Forum Type 2 Tag Operation specification in your case) yourself and write the NDEF message page-by-page.

    As NTAG216 should be discovered as MifareUltralight, the easiest way would be to use a MifareUltralight connection. You coud then

    1. do the authentication:

      mfu.transceive(new byte[]{ (byte)0x1b, pwd[0], pwd[1], pwd[2], pwd[3] });
      
    2. write the tag page-by-page (you probably need to write pages 4 and onwards which contain the NDEF message wrapped in a TLV structure with the tag 0x03, you might also need to write page 3 if you need to make any changes to the capability container):

      mfu.write(pageNumber, data)
      

      where data is the four byte data value that should be written to page pageNumber.