如何使用 NfcA class 读取 Mifare Classic 标签?
How to read the Mifare Classic tag using the NfcA class?
我有一个支持 NfcA
和 MifareClassic
技术的 NFC 标签。固件更新后,我的 phone 不再支持 MifareClassic
技术。在旧固件上,读取 MifareClassic
标签工作正常。
是否可以使用 NfcA
class 读取 Mifare Classic 标签?这怎么能做到?
Mifare Classic A0A1A2A3A4A5技术认证密钥(举例)
public static String[] readTag(Tag tag) {
byte[] readedData;
byte[] PASSWORD = new byte[]{(byte) 0xA0, (byte) 0xA1, (byte) 0xA2, (byte) 0xA3, (byte) 0xA4, (byte) 0xA5};
NfcA nfca = NfcA.get(tag);
try {
nfca.connect();
readedData = nfca.transceive(new byte[]{
(byte) 0x30,
(byte) (0 & 0x0ff),PASSWORD // (for example)
});
} catch (Exception e) {
}
}
Commands for transceive
首先,为了与 MIFARE Classic 标签进行通信(即验证、执行 read/write 操作),您将需要具有支持 MIFARE Classic 的 NFC 硬件的设备。由于恩智浦的许可政策,这通常只能在配备恩智浦 NFC 芯片组的设备上实现。其他 NFC 芯片组通常只允许您执行 anti-collision 和枚举(即检测标签并读取其 (N)UID)。
由于您指出访问 MIFARE Classic 的能力(通过 MifareClassic
标记技术对象)由于固件更新而丢失,我假设您的 NFC 芯片组能够访问 MIFARE Classic .
NXP 的 NFC 控制器使用 MIFARE reader 命令(plain-text 用于身份验证、二进制 read/write 和值块操作的命令)透明地抽象对 MIFARE Classic 标签的访问。芯片组自动负责将这些抽象命令转换为实际的 MIFARE Classic 命令、相互身份验证和会话加密。 MifareClassic
标记技术对象执行以下命令:
authenticateSectorWithKeyA(sectorIndex, key)
:
+----------+-------------+--------------------+-------------------+
| 0x60 | BLOCK_INDEX | UID (last 4 bytes) | KEY_A |
| (1 byte) | (1 byte) | (4 bytes) | (6 bytes) |
+----------+-------------+--------------------+-------------------+
authenticateSectorWithKeyB(sectorIndex, key)
:
+----------+-------------+--------------------+-------------------+
| 0x61 | BLOCK_INDEX | UID (last 4 bytes) | KEY_B |
| (1 byte) | (1 byte) | (4 bytes) | (6 bytes) |
+----------+-------------+--------------------+-------------------+
readBlock(blockIndex)
:
+----------+-------------+
| 0x30 | BLOCK_INDEX |
| (1 byte) | (1 byte) |
+----------+-------------+
writeBlock(sectorIndex, data)
:
+----------+-------------+--------------------+
| 0xA0 | BLOCK_INDEX | DATA |
| (1 byte) | (1 byte) | (16 bytes) |
+----------+-------------+--------------------+
increment(blockIndex, value)
:
+----------+-------------+-------------------+
| 0xC1 | BLOCK_INDEX | VALUE |
| (1 byte) | (1 byte) | (4 bytes) |
+----------+-------------+-------------------+
decrement(blockIndex, value)
:
+----------+-------------+-------------------+
| 0xC0 | BLOCK_INDEX | VALUE |
| (1 byte) | (1 byte) | (4 bytes) |
+----------+-------------+-------------------+
transfer(blockIndex)
:
+----------+-------------+
| 0xB0 | BLOCK_INDEX |
| (1 byte) | (1 byte) |
+----------+-------------+
restore(blockIndex)
:
+----------+-------------+
| 0xC2 | BLOCK_INDEX |
| (1 byte) | (1 byte) |
+----------+-------------+
对于当前的 NFC 控制器(使用 NCI 的控制器;不适用于例如 PN544),这些命令被 Android NFC 系统服务(参见 phNxpExtns.c and phNxpExtns_MifareStd.c)包装到特殊的 NCI 命令中。
根据您的设备无法枚举 MifareClassic
标签技术的原因,您可能很幸运,并且您设备的 NFC 堆栈已经处理了该包装。在这种情况下,您应该能够使用 NfcA
标记对象发送上述命令。
但是,您的设备可能无法枚举 MifareClassic
标签技术,因为它只是将标签检测为常规类型 2 标签(或其他 NFC-A 标签)。在那种情况下,NativeNfcTag.cpp 将不会执行额外的包装。您仍然可以通过遵循 phNxpExtns.c and phNxpExtns_MifareStd.c 中执行的相同策略来实际创建包装命令。但是,我不确定其他 side-effects 不正确的检测可能还有什么(例如不同的接口初始化)。
我有一个支持 NfcA
和 MifareClassic
技术的 NFC 标签。固件更新后,我的 phone 不再支持 MifareClassic
技术。在旧固件上,读取 MifareClassic
标签工作正常。
是否可以使用 NfcA
class 读取 Mifare Classic 标签?这怎么能做到?
Mifare Classic A0A1A2A3A4A5技术认证密钥(举例)
public static String[] readTag(Tag tag) {
byte[] readedData;
byte[] PASSWORD = new byte[]{(byte) 0xA0, (byte) 0xA1, (byte) 0xA2, (byte) 0xA3, (byte) 0xA4, (byte) 0xA5};
NfcA nfca = NfcA.get(tag);
try {
nfca.connect();
readedData = nfca.transceive(new byte[]{
(byte) 0x30,
(byte) (0 & 0x0ff),PASSWORD // (for example)
});
} catch (Exception e) {
}
}
Commands for transceive
首先,为了与 MIFARE Classic 标签进行通信(即验证、执行 read/write 操作),您将需要具有支持 MIFARE Classic 的 NFC 硬件的设备。由于恩智浦的许可政策,这通常只能在配备恩智浦 NFC 芯片组的设备上实现。其他 NFC 芯片组通常只允许您执行 anti-collision 和枚举(即检测标签并读取其 (N)UID)。
由于您指出访问 MIFARE Classic 的能力(通过 MifareClassic
标记技术对象)由于固件更新而丢失,我假设您的 NFC 芯片组能够访问 MIFARE Classic .
NXP 的 NFC 控制器使用 MIFARE reader 命令(plain-text 用于身份验证、二进制 read/write 和值块操作的命令)透明地抽象对 MIFARE Classic 标签的访问。芯片组自动负责将这些抽象命令转换为实际的 MIFARE Classic 命令、相互身份验证和会话加密。 MifareClassic
标记技术对象执行以下命令:
authenticateSectorWithKeyA(sectorIndex, key)
:+----------+-------------+--------------------+-------------------+ | 0x60 | BLOCK_INDEX | UID (last 4 bytes) | KEY_A | | (1 byte) | (1 byte) | (4 bytes) | (6 bytes) | +----------+-------------+--------------------+-------------------+
authenticateSectorWithKeyB(sectorIndex, key)
:+----------+-------------+--------------------+-------------------+ | 0x61 | BLOCK_INDEX | UID (last 4 bytes) | KEY_B | | (1 byte) | (1 byte) | (4 bytes) | (6 bytes) | +----------+-------------+--------------------+-------------------+
readBlock(blockIndex)
:+----------+-------------+ | 0x30 | BLOCK_INDEX | | (1 byte) | (1 byte) | +----------+-------------+
writeBlock(sectorIndex, data)
:+----------+-------------+--------------------+ | 0xA0 | BLOCK_INDEX | DATA | | (1 byte) | (1 byte) | (16 bytes) | +----------+-------------+--------------------+
increment(blockIndex, value)
:+----------+-------------+-------------------+ | 0xC1 | BLOCK_INDEX | VALUE | | (1 byte) | (1 byte) | (4 bytes) | +----------+-------------+-------------------+
decrement(blockIndex, value)
:+----------+-------------+-------------------+ | 0xC0 | BLOCK_INDEX | VALUE | | (1 byte) | (1 byte) | (4 bytes) | +----------+-------------+-------------------+
transfer(blockIndex)
:+----------+-------------+ | 0xB0 | BLOCK_INDEX | | (1 byte) | (1 byte) | +----------+-------------+
restore(blockIndex)
:+----------+-------------+ | 0xC2 | BLOCK_INDEX | | (1 byte) | (1 byte) | +----------+-------------+
对于当前的 NFC 控制器(使用 NCI 的控制器;不适用于例如 PN544),这些命令被 Android NFC 系统服务(参见 phNxpExtns.c and phNxpExtns_MifareStd.c)包装到特殊的 NCI 命令中。
根据您的设备无法枚举 MifareClassic
标签技术的原因,您可能很幸运,并且您设备的 NFC 堆栈已经处理了该包装。在这种情况下,您应该能够使用 NfcA
标记对象发送上述命令。
但是,您的设备可能无法枚举 MifareClassic
标签技术,因为它只是将标签检测为常规类型 2 标签(或其他 NFC-A 标签)。在那种情况下,NativeNfcTag.cpp 将不会执行额外的包装。您仍然可以通过遵循 phNxpExtns.c and phNxpExtns_MifareStd.c 中执行的相同策略来实际创建包装命令。但是,我不确定其他 side-effects 不正确的检测可能还有什么(例如不同的接口初始化)。