使用收发器和react-native-nfc-manager读取MIFARE DESFire EV2 NFC卡上的文件

问题描述 投票:0回答:1

如何正确检索 MIFARE DESFire EV2 卡上的 x01 和 x02 文件中的数据?

我正在尝试读取 MIFARE DESFire EV2 卡上的两个文件,但没有收到预期的信息。另外,我找不到有关这些 MIFARE DESFire EV2 卡的任何文档。

这是我的代码,基于我在Google上找到的一些信息以及这个问题Android NFC IsoDep读取文件内容

const readNfc = async () => {
if (isReadingNfc) {
    return;
}
setIsReadingNfc(true);
let response = null;
try {
    await NfcManager.requestTechnology(NfcTech.NfcA);// IsoDep returns the same
    console.warn("1: requestTechnology");

    // select application (AID: 0xFFFFFF)
    await NfcManager.transceive([
        0x90, 0x5a, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0x00,
    ]);
    console.warn("2: application selected");

    // read file 0x01
    const fileX01 = await NfcManager.transceive([
        0x90, 0xbd, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00,
    ]);
    console.warn("3: fileX01", fileX01);

    const data1 = fileX01.slice(0, fileX01.length - 2).toString("ascii");


    // read file 0x02
    const fileX02 = await NfcManager.transceive([
        0x90, 0xbd, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00,
    ]);

    console.warn("4: fileX02", fileX02);

    const data2 = fileX02.slice(0, fileX02.length - 2).toString("ascii");

    response = {data1,data2,};

    console.warn("5: response ", response);

    setNfcTagData(response);
} catch (error) {
    setNfcError(error);
} finally {
    await NfcManager.cancelTechnologyRequest();

setIsReadingNfc(false);
}

返回响应; };

日志总是返回以下内容: '5: 文件X01', [ 145, 157 ] '6: 文件X02', [ 145, 157 ]

我假设 145 和 157 是十六进制的 91 和 9D,它们可能是错误代码,但它们是什么意思?

这是我尝试从 NFC Taginfo 应用程序读取的卡的报告:

** TagInfo Scan (version 5.0.0) 20-mars-24 15:10:49 **
Report Type: -- IC INFO ------------------------------
# IC Manufacturer:
Probably Genuine - AES OC couldn't be performed
NOTE: To perform AES Originality check, enable the option "Originality Check" from settings if not done, and make sure internet connection is active.
# IC Type:
MIFARE DESFire EV2 (MF3D22)
# DESFire Applications:
General issuer info
-- NDEF ------------------------------
# No NDEF Data Storage Populated:
-- EXTRA ------------------------------
# Memory information:
Size: 2 kB
Available: 2.0 kB
# IC Information:
Capacitance: 17 pF
# Version information:
Vendor ID: Probably Genuine - AES OC couldn't be performed
Hardware info:
* Type/subtype: 0x01/0x01
*  Major Version: 0x12
*  Minor Version: 0x00
* Storage size: 2048 bytes
* Protocol: ISO/IEC 14443-4
Software info:
* Type/subtype: 0x01/0x01
*  Major Version: 0x02
*  Minor Version: 0x01
* Storage size: 2048 bytes
* Protocol: ISO/IEC 14443-4
Production date: week 27, 2018
# Authentication Information:
Default PICC master key
# Originality Check (asymmetric):
Signature verified with NXP public key
# TagInfo Version:
Version :5.0.0
# Device Info:
Device Model :HMD Global ( Nokia G42 5G )
Android OS Version :14
-- FULL SCAN ------------------------------
# Technologies Supported:
ISO/IEC 7816-4 compatible
Native DESFire APDU framing
ISO/IEC 14443-4 (Type A) compatible
ISO/IEC 14443-3 (Type A) compatible
ISO/IEC 14443-2 (Type A) compatible
# Android Technology Information:
Tag description:
* TAG: Tech [android.nfc.tech.IsoDep, android.nfc.tech.NfcA, android.nfc.tech.NdefFormatable]
* Maximum transceive length: 65279 bytes
* Default maximum transceive time-out: 2000 ms
* Extended length APDUs supported
* Maximum transceive length: 253 bytes
* Default maximum transceive time-out: 618 ms
# Detailed Protocol Information:
ID: 04:36:1F:12:AD:5F:80
ATQA: 0x4403
SAK: 0x20
ATS: 0x067577810280
* Max. accepted frame size: 64 bytes (FSCI: 5)
* Supported receive rates:
    - 106, 212, 424, 848 kbit/s (DR: 1, 2, 4, 8)
* Supported send rates:
    - 106, 212, 424, 848 kbit/s (DS: 1, 2, 4, 8)
* Different send and receive rates supported
* SFGT: 604.1 us  (SFGI: 1)
* FWT: 77.33 ms  (FWI: 8)
* NAD not supported
* CID supported
* Historical bytes: 0x80 |.|
# Memory Content:
Application ID 0x000000 (PICC)
* Default master key
* Key configuration:
  - 1 (3)DES key
  - Key type of active keyset: 2TDEA
  - Master key changeable
  - Master key required for:
    ~ directory list access: no
    ~ create/delete files: no
  - Configuration changeable
Application ID 0xFFFFFF (General issuer info)
* Key configuration:
  - 2 AES keys
  - Max no. of keys: 2
  - Key type of active keyset: AES
  - Master key changeable
  - Master key required for:
    ~ directory list access: no
    ~ create/delete files: yes
  - Configuration changeable
  - Master key required for changing a key
  - Key versions:
    ~ Master key: 0
    ~ Key #1: 0
  - File ID 0x00: Standard data, 32 bytes
    ~ Communication: encrypted
    ~ Read key: free access
    ~ Write key: key #1
    ~ Read/Write key: master key
    ~ Change key: master key
    ~ Contents:
[0000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
[0010] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
  - File ID 0x01: Standard data, 128 bytes
    ~ Communication: encrypted
    ~ Read key: free access
    ~ Write key: key #1
    ~ Read/Write key: master key
    ~ Change key: master key
    ~ Contents:
[0000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
[0010] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
[0020] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
[0030] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
[0040] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
[0050] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
[0060] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
[0070] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
  - File ID 0x02: Standard data, 32 bytes
    ~ Communication: encrypted
    ~ Read key: free access
    ~ Write key: key #1
    ~ Read/Write key: master key
    ~ Change key: master key
    ~ Contents:
[0000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
[0010] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
  - File ID 0x03: Standard data, 32 bytes
    ~ Communication: encrypted
    ~ Read key: free access
    ~ Write key: key #1
    ~ Read/Write key: master key
    ~ Change key: master key
    ~ Contents:
[0000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
[0010] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
  - File ID 0x04: Standard data, 32 bytes
    ~ Communication: encrypted
    ~ Read key: free access
    ~ Write key: key #1
    ~ Read/Write key: master key
    ~ Change key: master key
    ~ Contents:
[0000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
[0010] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
  - File ID 0x05: Standard data, 32 bytes
    ~ Communication: encrypted
    ~ Read key: free access
    ~ Write key: key #1
    ~ Read/Write key: master key
    ~ Change key: master key
    ~ Contents:
[0000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
[0010] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
--------------------------------------

我在这里隐藏了数据,但卡片上除了 00 之外还有其他信息! 根据我从报告中了解到的情况,如果我是正确的,读取文件不需要密钥,它们位于 0xFFFFFF 应用程序中。

那么我如何正确地从 x01 和 x02 文件中检索数据?

android nfc mifare react-native-nfc-manager desfire
1个回答
0
投票

这是我的想法,我通过错误处理检索了所有必要的数据:

    // Reads the remaining NFC data fragments following an initial response.
    // This function continues to request additional NFC data frames until the NFC tag indicates no more frames.
    const readRemainingNfcData = async (initialResponse) => {
        let response = initialResponse;
        let keepReading = true;

        while (keepReading) {
            const status = response.slice(-2);

            // 0xAF(175) says Additional data frame is expected to be sent
            if (status[0] === 0x91 && status[1] === 0xaf) {
                // Get the continuation of the response.
                const rBlockResponse = await NfcManager.transceive([
                    0x90, 0xaf, 0x00, 0x00, 0x00,
                ]);

                if (rBlockResponse && rBlockResponse.length > 2) {
                    response = response
                        .slice(0, -2)
                        .concat(rBlockResponse.slice(0, -2));
                } else {
                    throw new Error("Failed to read remaining NFC data");
                }
            } else {
                keepReading = false;
            }
        }

        return response;
    };

    // Check for error codes from the response received from the NFC card.
    // Here is a list of status:
    // https://www.eftlab.com/knowledge-base/complete-list-of-apdu-responses
    const handleResponse = (response) => {
        const status = response.slice(-2);

        if (
            !(status[0] === 0x91 && status[1] === 0) && // OK
            !(status[0] === 0x91 && status[1] === 0xaf) && // Additional data frame is expected to be sent
            !(status[0] === 0 && status[1] === 0)
        ) {
            throw new Error(
                `NFC read error with status: ${status[0].toString(16)} ${status[1].toString(16)}`,
            );
        }
    };

    const readNfc = async () => {
        if (isReadingNfc) {
            return;
        }

        setIsReadingNfc(true);
        let tag = null;
        let response = null;

        try {
            await NfcManager.requestTechnology(NfcTech.IsoDep);
            // tag = await NfcManager.getTag();

            // Select application FFFFFF
            const selectApplication = await NfcManager.transceive([
                0x90, 0x5a, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0x00,
            ]);

            handleResponse(selectApplication);

            // Read the file 2
            const fileX02 = await NfcManager.transceive([
                0x90, 0xbd, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00,
            ]);

            handleResponse(fileX02);

            // Read the file 1
            let fileX01 = await NfcManager.transceive([
                0x90, 0xbd, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00,
            ]);

            handleResponse(fileX01);

            // File 1 is longer than maximum transceive max data transfer
            fileX01 = await readRemainingNfcData(fileX01);

            handleResponse(fileX01);

            response = {
                badgeData: decodeAscii(fileX01),
                badgeType: decodeAscii(fileX02),
            };

            setNfcTagData(response);
        } catch (error) {
            setNfcError(error);
        } finally {
            await NfcManager.cancelTechnologyRequest();

            setIsReadingNfc(false);
        }

        return response;
    };
© www.soinside.com 2019 - 2024. All rights reserved.