简体   繁体   English

读取第二扇区和更多MIFARE Classic卡时出现错误6800

[英]Error 6800 on reading 2nd sector and more of a MIFARE Classic card

I use nfc-pcsc to read a MIFARE Classic 1K card with the ACR122U reader (USB connection). 我使用nfc-pcsc和ACR122U读卡器(USB连接)读取MIFARE Classic 1K卡。 But I often get a 0x6800 error: 但是我经常收到一个0x6800错误:

  • Sometimes when I read 1st sector (blocks 4-5-6) 有时,当我阅读第一扇区时(4-5-6方框)
  • Always when I read 2nd sector and more (blocks 8-9-10, 12-13-14, etc.) 总是在我阅读第二扇区及更多内容时(8-9-10、12-13-14块等)

But a native software like NFC-GUI can read/write all data with no difficulties. 但是像NFC-GUI这样的本地软件可以轻松读取/写入所有数据。

The keys A/B are default keys (000000.... and FFFFFF....). 按键A / B是默认按键(000000 ....和FFFFFF ....)。 The access bits have default values of an empty card. 访问位具有空卡的默认值。

Why this error? 为什么会出现这个错误? How can I read the card without error? 如何正确读取卡?

Note that I can read a MIFARE Ultralight card without difficulties. 请注意,我可以毫无困难地读取MIFARE Ultralight卡。

NodeJS code (same as example of NFC-PCSC): NodeJS代码(与NFC-PCSC的示例相同):

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

const TAG_ISO_14443_3 = 'TAG_ISO_14443_3'; // ISO/IEC 14443-3 tags
const TAG_ISO_14443_4 = 'TAG_ISO_14443_4'; // ISO/IEC 14443-4 tags
const KEY_TYPE_A = 0x60;
const KEY_TYPE_B = 0x61;


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

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

    console.log(`${reader.reader.name}  device attached`);

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

        const CLASSIC_1K = '000100000000';
        const CLASSIC_4K = '000200000000';
        const ULTRALIGHT = '000300000000';


        console.log(`${reader.reader.name}  card detected`, card);

        let buf     = card.atr;
        let type    = buf.slice(0,12).toString('hex').toUpperCase();
        let version = null;

        if (type == '3B8F8001804F0CA000000306')
        {
            version = card.atr.slice(13,19).toString('hex');
            switch (version)
            {
                case '000100000000':
                    console.log('Mifare Classic 1k');
                    break;
                case '000200000000':
                    console.log('Mifare Classic 4k');
                    break;
                case '000300000000':
                    console.log('Mifare Ultralight');
                    break;
                default:
                    console.log('Other card');
            }
        }

        if (version == ULTRALIGHT)
        {
            .... (no difficulties)
        }
        else if (version == CLASSIC_1K)
        {

            const key_a = '000000000000'; 
            const key_b = 'FFFFFFFFFFFF'; 
            const keyTypeA = KEY_TYPE_A;
            const keyTypeB = KEY_TYPE_B;

            Promise.all([
                // Sector 1
                reader.authenticate(4, keyTypeB, key_b),
                reader.authenticate(5, keyTypeB, key_b),
                reader.authenticate(6, keyTypeB, key_b),
                // Sector 2
                reader.authenticate(8, keyTypeB, key_b),
                reader.authenticate(9, keyTypeB, key_b),
                reader.authenticate(10, keyTypeB, key_b),
            ]).
            then(() => {
                console.info(`blocks successfully authenticated`);
                reader.read(4, 32, 16) // Often OK
                .then(data => {
                    console.info(`data read`, data.toString());
                    return reader.read(8, 32, 16); // Always error
                })
                .then(data => {
                    console.info(`data read`, data.toString());
                }
                .catch(err => {
                    console.error(`error when reading data`);
                })
            })
            .catch(() => {
                console.info(`athentification error`);
            });

        }


    });

    reader.on('card.off', card => {
        console.log(`${reader.reader.name}  card removed`);
    });

    reader.on('error', err => {
        console.log(`${reader.reader.name}  an error occurred`, err);
    });

    reader.on('end', () => {
        console.log(`${reader.reader.name}  device removed`);
    });

});

nfc.on('error', err => {
    console.log('an error occurred', err);
});

It seems that you first authenticate to all sectors and then try to read some data from these sectors. 看来您首先要对所有扇区进行身份验证,然后再尝试从这些扇区读取一些数据。 However, this is not how MIFARE Classic authentication works. 但是,这不是MIFARE Classic身份验证的工作方式。 Instead, will need to authenticate to a sector (eg use reader.authenticate(4, keyTypeB, key_b) to authenticate with key B for the whole sector 1). 相反,将需要对一个扇区进行身份验证(例如,使用reader.authenticate(4, keyTypeB, key_b)对整个扇区1的密钥B进行身份验证)。 You can then read data from any block of that sector (where key B is granted read access). 然后,您可以从该扇区的任何块中读取数据(已授予键B的读取访问权限)。 After you finished reading from that sector, you can authenticate to the next sector (eg reader.authenticate(8, keyTypeB, key_b) to authenticate with key B for the whole sector 2). 从该扇区读取完后,可以对下一个扇区进行身份验证(例如, reader.authenticate(8, keyTypeB, key_b)以对整个扇区2的密钥B进行身份验证)。 You can then read data from any block of that sector (where key B is granted read access). 然后,您可以从该扇区的任何块中读取数据(已授予键B的读取访问权限)。

Also note that the default configuration for "empty" MIFARE Classic cards is Key A = FFFFFFFFFFFF, Key B = not used, read/write with Key A only. 另请注意,“空” MIFARE Classic卡的默认配置为Key A = FFFFFFFFFFFF,Key B =未使用,仅使用Key A进行读/写。 Since, the areas containing the keys are not readable (unless a key is not used), reading "000000000000" from those memory regions usually just means that no data could be read, the actual key could still be some other value. 由于包含密钥的区域是不可读的(除非不使用密钥),因此从那些存储区域中读取“ 000000000000”通常仅意味着无法读取任何数据,因此实际密钥仍可能是其他值。 Thus, if you are sure that the cards a empty and have default permissions set, I would suggest to try to authenticate using "FFFFFFFFFFFF" as key A: 因此,如果您确定卡为空并且设置了默认权限,则建议尝试使用“ FFFFFFFFFFFF”作为密钥A进行身份验证:

const key_a = 'FFFFFFFFFFFF'; 
const keyTypeA = KEY_TYPE_A;
await reader.authenticate(4, keyTypeA, key_a);
console.info(`sector authenticated`);
const data1 = await reader.read(4, 48, 16);
console.info(`data read for sector 1`, data1.toString());
await reader.authenticate(8, keyTypeA, key_a);
const data2 = await reader.read(8, 48, 16);
console.info(`data read for sector 2`, data2.toString());

Note: It seems that the source of confusion was misleading documentation in the MIFARE Classic example that shipped with nfc-pcsc. 注意:似乎混乱的根源是nfc-pcsc附带的MIFARE Classic示例中的误导性文档。 The documentation has been updated. 该文档已更新。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM