I am trying to set and check a password in a NFC Tag (type: NTAG213) but I always receive an IOException
(Transceive failed) when I am trying to set it.
I don't understand which page I have to set for password and ACK pack. This is my code written in C# with Xamarin. Please feel free to reply in native Android Java code.
var tag = intent.GetParcelableExtra (NfcAdapter.ExtraTag) as Tag;
String password = "pass";
byte[] array = System.Text.Encoding.ASCII.GetBytes (password);
MifareUltralight mifare = MifareUltralight.Get (tag);
mifare.Connect ();
byte[] result1 = mifare.Transceive(new byte[] {
(byte)0xA2, /* CMD = WRITE */
(byte)0x2C, /* PAGE = 44 */
array[0], array[1], array[2], array[3]
});
byte[] result2 = mifare.Transceive(new byte[] {
(byte)0xA2, /* CMD = WRITE */
(byte)0x2A, /* PAGE = 42 */
(byte)array[0], (byte)array[1], (byte)0, (byte)0
});
With NTAG213, the correct pages for the password (PWD) and the password acknowledge (PACK) are:
0x2B
)0x2C
)Hence, you are trying to write to the wrong pages. More specifically, you are trying to write non-zero values to RFUI bytes (page 44, bytes 2-3 and page 42, bytes 1-3) which may cause the write operations to fail.
So you would typically want to do something like this:
byte[] pwd = new byte[] { (byte)0x70, (byte)0x61, (byte)0x73, (byte)0x73 };
byte[] pack = new byte[] { (byte)0x98, (byte)0x76 };
// write PACK:
byte[] result = mifare.Transceive(new byte[] {
(byte)0xA2, /* CMD = WRITE */
(byte)0x2C, /* PAGE = 44 */
pack[0], pack[1], 0, 0
});
// write PWD:
result = mifare.Transceive(new byte[] {
(byte)0xA2, /* CMD = WRITE */
(byte)0x2B, /* PAGE = 43 */
pwd[0], pwd[1], pwd[2], pwd[3]
});
Note that it does not make much sense to let PACK be a subset of PWD since an attacker would then be able to obtain the PACK value from the PWD value. The PACK value is typically used as a shared secret that only you and the tag "know" and that the tag sends in response to a successful authentication attempt in order to prove that it is a genuine tag. (Though there are quite a lot of security issues with this approach.)
Further note that setting the PWD/PACK values will fail (possibly with an IOException
) if the tag is already protected (password set and authentication configuration set to protect PWD/PACK). In those cases, you would need to authenticate with the current password first.