Skip to content
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

Mifare Ultralight NTAG213 - writing data is senselessly after setting the password configuration #99

Closed
VictorGorban opened this issue Jun 18, 2020 · 1 comment

Comments

@VictorGorban
Copy link

VictorGorban commented Jun 18, 2020

Steps to reproduce:

  1. authenticate empty card with default password [0,0,0,0]
  2. read empty data
  3. write data
  4. write password
  5. write configuration
  6. reconnect the card
  7. read data // data was written
  8. write data // senselessly now, nothing changes
  9. reconnect the card
  10. read the data // see that nothing changed at the step 8.

To see the problem, you can re-run the "mifare-ultralight-ntag.js" example couple of times with different data to write.
I have Mifare Ultralight NTAG213, see memory organization and configuration pages
Code snippet:

nfc.on('reader', async reader => {

	pretty.info(`device attached`, reader);
	const ultralight = new MifareUltralight(reader);

	reader.on('card', async card => {

		pretty.info('card detected', reader, card);

		let password = 'FFFFFFFF'; // default password: hex string => [255,255,255,255]
		let pack = '0000'; // default pack: hex string => [0,0]

		password = Buffer.from(password, 'hex')
		pack = Buffer.from(pack, 'hex')

		try {

			await ultralight.passwordAuthenticate(password, pack);
			pretty.info('passwordAuthenticate: successfully authenticated');

		} catch (err) {
			pretty.error('passwordAuthenticate error:', err);
		}

		let hasToWriteConfig = true;
		try {

			const data = await reader.read(5, 8);
			if (data[0] != 0) { // if not empty (maybe already password protected), do not write the config.
				hasToWriteConfig = false;
			}
			pretty.info('fastRead data:', data);

		} catch (err) {
			pretty.error('fastRead error:', err);
			return;
		}

		// Note! UPDATE locations of configuration pages according to the version of your card!
		// (see memory layout in your card's docs)

		try {

			let data = Buffer.from([5, 5, 5, 5]) // for step 8, set it to something different.
			await reader.write(5, data) // data not changing after writing config (step 5)
			console.log('data written successfully')

		} catch (err) {
			pretty.error('write error', err)
			return;
		}

		if (!hasToWriteConfig) {
			return;
		}

		try {

			// set custom PASSWORD (4 bytes) (stored in page 43)
			await reader.write(43, password);

			// read current configuration
			const config = await reader.read(41, 4);

			console.log(config[0]);
			console.log(config[1]);
			console.log(config[2]);
			console.log(config[3]); // AUTH0 (default: 0xff)

			// Protect everything (start with first data page)
			config[3] = 0x04;

			await reader.write(41, config); // After this, 1) writing is broken. 2) on second read, reading returns me empty buffer

		} catch (err) {
			pretty.error('configuration write error:', err);
		}

	});

	reader.on('error', err => {
		pretty.error(`an error occurred`, reader, err);
	});

	reader.on('end', () => {
		pretty.info(`device removed`, reader);
	});

});

Also, if you will try to write config after step 8, it will throw an error. Writing password does without errors, though.

@VictorGorban VictorGorban changed the title Mifare Ultralight NTAG213 - writing data is senselessly after setting the password configuration NTAG213 - writing data is senselessly after setting the password configuration Jun 29, 2020
@VictorGorban VictorGorban changed the title NTAG213 - writing data is senselessly after setting the password configuration Mifare Ultralight NTAG213 - writing data is senselessly after setting the password configuration Jun 29, 2020
@VictorGorban
Copy link
Author

VictorGorban commented Jul 6, 2020

OK, I finally fixed the problem. Just one thing -
we need to (set password) and (authenticate and read/write) in two different sessions.

The following code clears my words:

 reader.on('card', async card => {
	pretty.info('card detected', reader, card);
	let action = 'password'; // read_auth, write_auth, read_write_auth

	let password = '0000';
	password = Buffer.from(password)

	if (action.includes('auth')) {
		// authenticate
	}

	if (action.includes('write')) {
		// do write
	}

	if (action.includes('read')) {
		// do read
	}

	if (action == 'password') {
		// set password, then write config
	}
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant