-
Notifications
You must be signed in to change notification settings - Fork 129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NTAG 21x Authentication #36
Comments
Hi @bierlair, thank you for posting your issue here. According to the official documentation, it is possible to protect NTAG21x cards with password. And all these things should be doable using ACR122U and nfc-pcsc library. 😃 I don't know, where the problem might be. Could you please answer the following questions so that we can find why it doesn't work?
Hope it helps. 🙂 Looking forward to your reply. I believe we make it work together. 🙂 To be honest, I have never tried to access protected cards before. I don't have any experience with NTAG21x cards (only with Mifare Ultralight EV1, Classic, and DESFire EV1). Fortunately, according to the documentation, I have been able to make it work on Mifare Ultralight EV1 (it is very similar to NTAG21x cards, it even uses same commands). After I issue PWD_AUTH command, I am able to read the (password-read-protected) memory. 🚀 Here is my code to authenticate card: reader.on('card', async card => {
console.log('card detected', card);
// PASSWORD (4 bytes) (stored on card in page 18)
const password = Buffer.from([
0xff,
0xff,
0xff,
0xff,
]);
// PACK (2 bytes) (stored in page 19 as first two bytes)
// PACK is the response from card in case of successful PWD_AUTH cmd
const pack = Buffer.from([
0xab,
0xcd
]);
try {
// CMD: PWD_AUTH via Direct Transmit (ACR122U) and Data Exchange (PN533)
const cmd = Buffer.from([
0xFF, // Class
0x00, // Direct Transmit (see ACR122U)
0x00, // ...
0x00, // ...
0x07, // Length of Direct Transmit payload
// Payload (7 bytes)
0xd4, // Data Exchange Command (see PN533 docs)
0x42, // inserted
0x1b, // PWD_AUTH
...password,
]);
console.log('pwd_auth cmd', cmd);
const response = await reader.transmit(cmd, 7);
console.log('pwd_auth response', response);
// pwd_auth response should look like the following (7 bytes)
// d5 43 00 ab cd 90 00
// byte 0: d5 prefix for response of Data Exchange Command (see PN533 docs)
// byte 1: 43 prefix for response of Data Exchange Command (see PN533 docs)
// byte 2: Data Exchange Command Status 0x00 is success (see PN533 docs)
// bytes 3-4: Data Exchange Command Response – our PACK (set on card in page 19, in bytes 0-1) from card
// bytes 5-6: ACR122U success code
} catch (err) {
console.error('pwd_auth error', err);
return;
}
}); That's how I set up the password protection (don't allow to read content without authentication): reader.on('card', async card => {
try {
// set custom PASSWORD (4 bytes) (stored in page 18)
await reader.write(19, password);
// set custom PACK (2 bytes) (stored in page 19 as first two bytes)
const packPage = await reader.read(19, 4);
packPage[0] = pack[0];
packPage[1] = pack[1];
await reader.write(19, packPage);
// read current configuration
const config = await reader.read(16, 8);
// Configuration page 16
console.log(config[0]);
console.log(config[1]);
console.log(config[2]);
console.log(config[3]); // AUTH0 (default: 0xff)
// Configuration page 17
console.log(config[4]); // ACCESS
console.log(config[5]); // VCTID (default: 0x05)
console.log(config[6]);
console.log(config[7]);
// Protect everything (start with first data page)
config[3] = 0x04;
// set ACCESS bits
// bit 7: PROT One bit inside the ACCESS byte defining the memory protection
// 0b ... write access is protected by the password verification
// 1b ... read and write access is protected by the password verification
// bit 6: CFGLCK Write locking bit for the user configuration
// - 0b ... user configuration open to write access
// - 1b ... user configuration permanently locked against write access
// bits 5-3: reserved
// bits 2-0: AUTHLIM
// bit number-76543210
// ||||||||
config[4] = 0b10000000;
// set custom access rules
await reader.write(16, config);
} catch (err) {
console.error(err);
}
}); |
Awesome, this is exactly what I needed. Since I am working with NTAG216, I needed to adjust the page addresses. The try/catch block for setting the password now looks something like this: try {
// set custom PASSWORD (4 bytes) (stored in page 229)
await reader.write(229, password);
// set custom PACK (2 bytes) (stored in page 230 as first two bytes)
const packPage = await reader.read(230, 4);
packPage[0] = pack[0];
packPage[1] = pack[1];
await reader.write(230, packPage);
// read current configuration
const config = await reader.read(227, 8);
// Configuration page 16
console.log(config[0]);
console.log(config[1]);
console.log(config[2]);
console.log(config[3]); // AUTH0 (default: 0xff)
// Configuration page 17
console.log(config[4]); // ACCESS
console.log(config[5]); // VCTID (default: 0x05)
console.log(config[6]);
console.log(config[7]);
// Protect everything (start with first data page)
config[3] = 0x04;
// set ACCESS bits
// bit 7: PROT One bit inside the ACCESS byte defining the memory protection
// 0b ... write access is protected by the password verification
// 1b ... read and write access is protected by the password verification
// bit 6: CFGLCK Write locking bit for the user configuration
// - 0b ... user configuration open to write access
// - 1b ... user configuration permanently locked against write access
// bits 5-3: reserved
// bits 2-0: AUTHLIM
// bit number-76543210
// ||||||||
config[4] = 0b10000000;
// set custom access rules
await reader.write(227, config);
} catch (err) {
console.error(err);
} Thanks again 👍 |
@bierlair That's great. 👍 So everything works as expected? Can we close the issue? BTW I think, it would be useful to have this in the examples. Thank you very much for pointing it out to me. In future, the examples should explain the basic usage and commands of the most popular cards and tags to help people to get started easily. From my experience, I can say, that regarding NFC standards and cards, there is a lack of documentation (or it is poor, hard to find and understand, especially for beginners). PS Don't forget to star ⭐️ my library, if you find it useful. 😃 Thanks. |
Everything works as expected. With this I was actually able to break it down even further. Here is something quick and dirty that helps identify the NTAG chip. Next step would be to return the appropriate offsets in an object property, such as model.offset = 123
Reference guide for this:
And yes, NFC technical guides are tough to dig through. So good code examples would help beginners to kick off faster. Cheers :-) |
@pokusew Hello, I am currently using ACS ACR 1252 1S CL Reader PICC 0 for my Mifare Ultralight. I wish to add a password to my tag so that others can write on it if they enter the password. Could I know what platform are you guys using to code and link with the reader because I am unable to find it. Thank you! |
Hello, I want to add a password protection after writing data on NTAG216. I tried @bierlair code sample but the last writing command break my nfc cards... This in my code:
Could you please help me to find a solution ? Thanks all |
Is there a way to password protect NTAG21X cards / Type TAG_ISO_14443_3 via ACR122U?
I was trying my luck with a previously posted thread about Mifare Ultralight cards, but I end up with 0x6300 errors.
Code:
This works, but any read or write attempt after, does not work anymore:
The text was updated successfully, but these errors were encountered: