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 Classic 1K: Unable to authenticate and read from tag #103

Open
timonsku opened this issue Sep 15, 2020 · 3 comments
Open

Mifare Classic 1K: Unable to authenticate and read from tag #103

timonsku opened this issue Sep 15, 2020 · 3 comments

Comments

@timonsku
Copy link

timonsku commented Sep 15, 2020

I'm trying to read the NDEF record on a Mifare Classic 1K tag. This works fine using the "NFC Tools" app from WakeDev. I can read and write with that just fine.

With nfc-pcsc I can detect the card but reading from it fails. So I tried to authenticate as explained in the Mifare Classic example but I'm simply not able to authenticate. I tried all known public keys, none of them seem to work. Am I doing something wrong?

require('nfc-pcsc');
const { NFC } = require('nfc-pcsc');

const nfc = new NFC(); // optionally you can pass logger

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

	console.log(`${reader.reader.name}  device attached`);
	reader.on('card', async card => {
		console.log(`${reader.reader.name}  card detected`, card);
		//const key = 'FFFFFFFFFFFF'; // key must be a 12-chars HEX string, an instance of Buffer, or array of bytes
		const keyType = reader.KEY_TYPE_A;
		const keys = [
		"ffffffffffff",
		"a0b0c0d0e0f0",
		"a1b1c1d1e1f1",
		"a0a1a2a3a4a5",
		"b0b1b2b3b4b5",
		"4d3a99c351dd",
		"1a982c7e459a",
		"000000000000",
		"aabbccddeeff",
		"d3f7d3f7d3f7",
		"aabbccddeeff",
		"714c5c886e97",
		"587ee5f9350f",
		"a0478cc39091",
		"533cb6c723f6",
		"8fd0a4f256e9"
		]
		keys.forEach(async key => {
	
			try {
				console.log(key)
				await reader.authenticate(4, keyType, key);
				console.log(`sector 1 successfully authenticated`, reader);

			} catch (err) {
				console.log(`error when authenticating block 4 within the sector 1`, reader, err);
				return;
			}
		});
		
		try {
				const data = await reader.read(4, 16, 16); // blockSize=16 must specified for MIFARE Classic cards
				console.log(`data read`, data);
				const payload = data.toString(); // utf8 is default encoding
				console.log(`data converted`, payload);
			} catch (err) {
			console.error(`error when reading data`, err);
		}
		
		

	});
 //...
});

Authentication errors out for every key and the read of course subsequentially also fails with the message error when reading data ReadError: Read operation failed: Status code: 0x6581

@eeemarv
Copy link

eeemarv commented Dec 6, 2020

Probably because the code tries to do multiple authentications in parallel, not sequentially?

@SomeDevWeb
Copy link

Hello.
Firstly, thanks for the effort involved in creating this package.
I am very new to RFID and NFC and I tried a few examples which seem to work in as much as getting the basic card info: buffer, tag, uid.

I got stuck with a similar problem like above: I need to get that actual "Record 0" and I don't really have too much time or knowledge to read through the documentation and wrap my head around exactly how to do it.

So I was wondering if there is any simple example of how to just read that "Record0", whether it's a text or URL or whatever is written there.

If useful, this is the info of the card I am testing with:
Tag type: ISO 14443-3A (NXP MIFARE Classic 1k)
Technologies available: NfcA, MifareClassic, Ndef
Memory: 1 kBytes: 16 sectors of blocks (16 bytes per block)
Data format: NXP wMifare Classic

Thank you so much in advance for your support!

@chris-mck
Copy link

chris-mck commented Sep 8, 2021

EDIT: Actually, using KEY_TYPE_B with key=0xFFFFFFFFFFFF does work. I must have been trying many combinations and missed that. So it looks like the wakdev app blocks reading with KEYA or it changes KEYA to something that is not all 0xFF or all 0x00. My below code works if changing the key type to KEY_TYPE_B.


I have the same problem as timonsku: I write data to the card with wakdev's NFC Tools app (Android), and can read it back in that app. I note that the KEYA and KEYB are not readable due to a change in the access bits done by the wakdev app, but I'm assuming that it left them as all 0xFF's.

Trying to read the card with nfc-pcsc gives "AuthenticationError: Authentication operation failed: Status code: 0x6300". My cards are MiFare Classics. If I try to use KEY_TYPE_B it still fails.

Below is my relevant code. NB: I wrote a URL record to the Card, so I want to skip into block 5 to avoid the record type bytes and only look at the end of the URL which has text for my application to process.

///Utils
const utils = require('./utils')

///NFC 
const { NFC } = require('nfc-pcsc');
const KEY_TYPE_A = 0x60;
const KEY_TYPE_B = 0x61; // key types from nfc-pcsc/src/Reader.js
var nfc = new NFC();

///NFC HANDLER 
nfc.on('reader', reader => {
 
    utils.LogThis("NFC HANDLER",`${reader.reader.name}  device attached`);
    
    reader.on('card', async card => {
     utils.LogThis("NFC HANDLER","Card detected" + card.uid);
    
        try {
	    // For MiFare Classic we need to authenticate every read+write
	    await reader.authenticate(4, KEY_TYPE_A, 'ffffffffffff'); // THIS LINE FAILS
	    // In MiFare Classic, the record type starts at block 4 but has
	    // non-text at the start. Jump to block 5 instead, which is
	    // partway through the text but still has what we're after.
            const ndchunck = await reader.read(5,32,16);
	    utils.LogThis(`NFC RAW`, ndchunck);
            const ndpayload = ndchunck.toString(); // utf8 is default encoding
	    utils.LogThis("NFC DATA", `data: ` + ndpayload);
        } catch (err) {
            utils.LogThisError("NFC HANDLER",`error when reading data in try` + err);
        }
    });
 
    reader.on('card.off', card => {  
        utils.LogThis("NFC HANDLER",`Card removed ` + card.uid);
    });
 
    reader.on('error', async err => {
        utils.LogThisError("NFC HANDLER",`error when reading data` + err);
    });
 
    reader.on('end', () => {
        utils.LogThis("NFC HANDLER",`${reader.reader.name}  device removed`);
    });
 
});

nfc.on('error', err => {
    utils.LogThisError("NFC HANDLER",`an error occurred` + err);
});

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

4 participants