问题
I would like to be able to set and unset password protection on a MIFARE Ultralight EV1 (MFOUL21) tag using the NfcA?
tag technology on Android.
I understand I would use the nfcA.transceive()
method for this, but I'm not sure what the arguments to that method would be, so could anyone provide code snippets to set and unset the password?
Update:
With respect to the TapLinx library, I would basically like the nfcA.transceive(...)
code snippets equvalent to:
ultralightEV1.programPwd(passwordBytes);
ultralightEV1.programPack(packBytes);
ultralightEV1.enablePasswordProtection(enabled, fromPageNum);
ultralightEV1.authenticatePwd(passwordBytes);
回答1:
Authenticate
ultralightEV1.authenticatePwd(passwordBytes);
In order to authenticate with the password to a MIFARE Ultralight EV1 tag (or NTAG21x), you would need to send the PWD_AUTH (0x1B) command (and possibly verify if the PACK response matches your expectations):
byte[] pass = { (byte)0x12, (byte)0x34, (byte)0x56, (byte)0x78 };
byte[] pack = { (byte)0x9A, (byte)0xBC };
byte[] response = nfc.transceive(new byte[] {
(byte) 0x1B, // PWD_AUTH
pass[0], pass[1], pass[2], pass[3]
});
if ((response != null) && (response.length >= 2)) {
// success
byte[] packReceived = Arrays.copyOf(response, 2);
if (Arrays.equal(packReceived, pack)) {
// PACK verified, so tag is authentic (not really, but that whole
// PWD_AUTH/PACK authentication mechanism was not really meant to
// bring much security, I hope; same with the NTAG signature btw.)
}
}
Set password and password-acknowledge
ultralightEV1.programPwd(passwordBytes); ultralightEV1.programPack(packBytes);
For MF0UL11, the password is on page 0x12 and the password-acknowledge (PACK) is on page 0x13 (configuration pages start at 0x10). For MF0UL21, the password is on page 0x27 and the password-acknowledge (PACK) is on page 0x28 (configuration pages start at 0x25).
In order to dynamically find out if your tag is MF0UL11 or MF0UL21, you could send a GET_VERSION (0x60) command:
int cfgOffset = -1;
byte[] response = nfc.transceive(new byte[] {
(byte) 0x60 // GET_VERSION
});
if ((response != null) && (response.length >= 8)) {
// success
if ((response[0] == (byte)0x00) && (response[1] == (byte)0x04)) {
// tag is from NXP
if (response[2] == (byte)0x03) {
// MIFARE Ultralight
if ((response[4] == (byte)0x01) && (response[5] == (byte)0x00) {
// MIFARE Ultralight EV1 (V0)
switch (response[6]) {
case (byte)0x0B:
// MF0UL11
cfgOffset = 0x010;
break;
case (byte)0x0E:
// MF0UL11
cfgOffset = 0x025;
break;
default:
// unknown
break;
}
}
}
}
}
Once you found the begin of the configuration pages, you can use a WRITE (0xA2) command to update the values of those pages (assuming you are authenticated with the current password otr the configuration pages are unprotected):
byte[] response = nfc.transceive(new byte[] {
(byte) 0xA2, // WRITE
(byte)((cfgOffset + 2) & 0x0FF), // page address
pass[0], pass[1], pass[2], pass[3] // new page data
});
response = nfc.transceive(new byte[] {
(byte) 0xA2, // WRITE
(byte)((cfgOffset + 3) & 0x0FF), // page address
pack[0], pack[1], (byte)0x00, (byte)0x00 // new page data (always need to write full page)
});
Enable password protection
ultralightEV1.enablePasswordProtection(enabled, fromPageNum);
In order to enable password protection, you need to cofigure the first page that requires the password (AUTH0, byte 3 on page 0x10 for MF0UL11/page 0x25 MF0UL21) and you need to configure the protection mode (PROT, bit 7 of byte 0 on page 0x11 for MF0UL11/page 0x26 MF0UL21).
You would typically first read (READ (0x30) command) the old value of those pages, update the affected bits and bytes, and write the new value to the tag:
int fromPageNum = 4;
boolean enableProtection = true;
boolean enableReadProtection = true;
byte[] response = nfc.transceive(new byte[] {
(byte) 0x30, // READ
(byte)(cfgOffset & 0x0FF) // page address
});
if ((response != null) && (response.length >= 16)) {
// success
// NOTE that READ will return *4 pages* starting at page address
byte auth0 = (byte)0xFF;
if (enableProtection || enableReadProtection) {
auth0 = (byte)(fromPageNum & 0x0FF);
}
byte[] writeResponse = nfc.transceive(new byte[] {
(byte) 0xA2, // WRITE
(byte)((cfgOffset + 0) & 0x0FF), // page address
response[0], response[1], response[2], auth0 // new page data
});
byte access = (byte)(response[4] & 0x07F);
if (enableProtection && enableReadProtection) {
access |= (byte)0x80;
}
byte[] writeResponse = nfc.transceive(new byte[] {
(byte) 0xA2, // WRITE
(byte)((cfgOffset + 1) & 0x0FF), // page address
access, response[5], response[6], response[7], // new page data
});
}
回答2:
You can use the TapLinx Library from NXP (available at https://www.mifare.net/en/products/tools/taplinx/) to communicate with MIFARE Ultralight EV1 in an abstracted manner.
To use "transceive", according to the datasheet available at http://www.advanide.com/wp-content/uploads/products/rfid/UltraLight%20EV1_MF0ULX1.pdf the WRITE Command (A2) needs to be used, with addresses 25-28h.
UPDATE: The commands to be sent should be (for MFOUL21):
ultralightEV1.programPwd(passwordBytes); A227AABBCCDD (for Password AABBCCDD)
ultralightEV1.programPack(packBytes); A228EEFF0000 (for PACK 0000)
ultralightEV1.enablePasswordProtection(enabled, fromPageNum); A225xx0000yy (where xx is the modulation mode; 00..strong mod. disabled; 01..strong mod enabled; yy = page where password protection starts)
ultralightEV1.authenticatePwd(passwordBytes); 1BAABBCCDD
来源:https://stackoverflow.com/questions/44395283/how-to-set-and-unset-password-on-a-mifare-ultralight-ev1-tag