如何正确检索 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 文件中检索数据?
这是我的想法,我通过错误处理检索了所有必要的数据:
// 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;
};