【问题标题】:Error 6800 on reading 2nd sector and more of a MIFARE Classic card读取 MIFARE Classic 卡的第二扇区和更多扇区时出现错误 6800
【发布时间】:2019-04-15 14:16:58
【问题描述】:

我使用 nfc-pcsc 通过 ACR122U 读卡器(USB 连接)读取 MIFARE Classic 1K 卡。但是我经常遇到0x6800错误:

  • 有时当我读取第一个扇区(4-5-6 块)时
  • 当我读取第 2 个扇区及更多扇区时(块 8-9-10、12-13-14 等)

但是像 NFC-GUI 这样的原生软件可以毫无困难地读取/写入所有数据。

A/B 键是默认键(000000.... 和 FFFFFF....)。访问位的默认值为空卡。

为什么会出现这个错误?怎样才能正确读卡?

请注意,我可以毫无困难地读取 MIFARE Ultralight 卡。

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);
});

【问题讨论】:

    标签: node.js express authentication nfc mifare


    【解决方案1】:

    您似乎首先对所有扇区进行身份验证,然后尝试从这些扇区读取一些数据。但是,这不是 MIFARE Classic 身份验证的工作方式。相反,需要对扇区进行身份验证(例如,使用reader.authenticate(4, keyTypeB, key_b) 使用密钥 B 对整个扇区 1 进行身份验证)。然后,您可以从该扇区的任何块中读取数据(密钥 B 被授予读取访问权限)。从该扇区完成读取后,您可以对下一个扇区进行身份验证(例如,reader.authenticate(8, keyTypeB, key_b) 使用密钥 B 对整个扇区 2 进行身份验证)。然后,您可以从该扇区的任何块中读取数据(密钥 B 被授予读取访问权限)。

    另请注意,“空”MIFARE Classic 卡的默认配置是 Key A = FFFFFFFFFFFF,Key B = 未使用,仅使用 Key A 读/写。由于包含密钥的区域不可读(除非未使用密钥),因此从这些内存区域读取“000000000000”通常意味着无法读取数据,实际密钥仍然可能是其他值。因此,如果您确定卡片为空并且设置了默认权限,我建议您尝试使用“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());
    

    注意: 混淆的根源似乎是 nfc-pcsc 附带的 MIFARE Classic 示例中的误导性文档。 The documentation has been updated.

    【讨论】:

    • 非常感谢!!我找了好几天的解决方案!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-29
    • 2022-07-08
    • 2016-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多