如何使用NfcA类阅读Mifare Classic标签?

时间:2017-08-05 14:35:29

标签: android authentication nfc mifare low-level

我有一个NFC标签,支持NfcAMifareClassic技术。固件更新后,我的手机不再支持MifareClassic技术。在较旧的固件上,阅读MifareClassic标记工作正常。

是否可以使用NfcA类来阅读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

1 个答案:

答案 0 :(得分:1)

首先,为了与MIFARE Classic标签进行通信(即验证,执行读/写操作),您将需要具有支持MIFARE Classic的NFC硬件的设备。由于恩智浦的许可政策,这通常只适用于恩智浦NFC芯片组的设备。其他NFC芯片组通常只允许您执行防冲突和枚举(即检测标签并读取其(N)UID)。

由于您表示由于固件更新而导致访问MIFARE Classic(通过MifareClassic标记技术对象)的功能丢失,我认为您的NFC芯片组能够访问MIFARE Classic。 / p>

恩智浦的NFC控制器使用MIFARE读取器命令(用于身份验证,二进制读/写和值块操作的纯文本命令)透明地抽象访问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系统服务包含在特殊的NCI命令中(参见phNxpExtns.cphNxpExtns_MifareStd.c)。

根据您的设备无法枚举MifareClassic标记技术的原因,您可能很幸运,设备的NFC堆栈已经处理了这种包装。在这种情况下,您应该能够使用NfcA标记对象发送上述命令。

但是,您的设备可能无法枚举MifareClassic标记技术,因为它只是将标记检测为常规的Type 2标记(或其他NFC-A标记)。在这种情况下,NativeNfcTag.cpp将不执行额外的包装。您仍然可以通过遵循phNxpExtns.cphNxpExtns_MifareStd.c中执行的相同策略来实际创建包装命令。但是,我不确定错误检测可能带来的其他副作用(例如,不同的接口初始化)。