Ошибка 6800 при чтении 2-го сектора и более карты MIFARE Classic - PullRequest
1 голос
/ 15 апреля 2019

Я использую nfc-pcsc для чтения карты MIFARE Classic 1K с помощью считывателя ACR122U (USB-соединение). Но я часто получаю ошибку 0x6800:

  • Иногда, когда я читаю 1-й сектор (блоки 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);
});

1 Ответ

0 голосов
/ 15 апреля 2019

Кажется, что вы сначала проходите аутентификацию во всех секторах, а затем пытаетесь прочитать некоторые данные из этих секторов. Однако это не то, как работает аутентификация MIFARE Classic. Вместо этого потребуется аутентификация в секторе (например, используйте reader.authenticate(4, keyTypeB, key_b) для аутентификации с ключом B для всего сектора 1). Затем вы можете читать данные из любого блока этого сектора (где ключу B предоставлен доступ для чтения). После того, как вы закончили чтение из этого сектора, вы можете аутентифицироваться в следующем секторе (например, reader.authenticate(8, keyTypeB, key_b), чтобы аутентифицироваться с ключом B для всего сектора 2). Затем вы можете читать данные из любого блока этого сектора (где ключу B предоставлен доступ на чтение).

Также обратите внимание, что конфигурация по умолчанию для «пустых» карт MIFARE Classic - это ключ A = FFFFFFFFFFFF, ключ B = не используется, чтение / запись только с ключом 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());

Примечание: Похоже, что источником путаницы была вводящая в заблуждение документация в примере MIFARE Classic, поставляемом с nfc-pcsc. Документация обновлена.

...