Tags 如何以编程方式检测NFC芯片的内存大小/页码

Tags 如何以编程方式检测NFC芯片的内存大小/页码,tags,nfc,rfid,mifare,fingerprinting,Tags,Nfc,Rfid,Mifare,Fingerprinting,除了探测特定的页码并检查它们是否存在之外,以编程方式检测NFC芯片(MIFARE Ultralight或NTAGxxx)的内存大小或页数的最简单方法是什么 ATR中是否有特定字节返回或存储在芯片内存保护区的某个位置,以确定它是特定的NTAGxxx芯片,还是页面计数或字节计数?通常,您只能通过大量指纹和读取命令探测来确定这一点 指纹识别:这意味着您需要一个制造商特定特征的数据库(例如,从数据表中收集,不幸的是,更经常的是,从经验测试中收集,因为大多数标签都没有(公开?或根本没有?)记录这些信息),

除了探测特定的页码并检查它们是否存在之外,以编程方式检测NFC芯片(MIFARE Ultralight或NTAGxxx)的内存大小或页数的最简单方法是什么


ATR中是否有特定字节返回或存储在芯片内存保护区的某个位置,以确定它是特定的NTAGxxx芯片,还是页面计数或字节计数?

通常,您只能通过大量指纹和读取命令探测来确定这一点

  • 指纹识别:这意味着您需要一个制造商特定特征的数据库(例如,从数据表中收集,不幸的是,更经常的是,从经验测试中收集,因为大多数标签都没有(公开?或根本没有?)记录这些信息),您可以对照这些信息检查标签

  • 探测:

    • 从第0页开始
    • 阅读页面
    • 成功时:将读取地址增加4页,然后重新开始
    • 失败时:将读取地址减1,然后再次尝试读取,直到找到可读地址
    • 在扇区结束时:从下一个扇区开始
    这样,您就可以找到最后一个可读的页面地址,它不一定是标记内存的“真实”端(例如,在端部可能有受保护的页面)

  • 如果您的Ultralight和NTAG标记是EV1标记(即,它们实现Ultralight EV1命令集),则expose a GET_VERSION命令可用于检索存储大小信息。版本信息与所有现有标签指纹数据库(您可以从Ultralight/NTAG数据表中获得该信息)相结合,将允许您可靠地1确定标签类型,从而确定内存大小

    1) 除了一些以“NTAG”出售的假冒芯片外,这些芯片模仿真实NTAG芯片的参数,但似乎内存大小、缺乏命令支持等与它们模仿参数的芯片不匹配


    当涉及到遵循NFC论坛类型2标记操作规范的NFC标记时,您还可以依赖编码到功能容器中的标记内存大小。但是,此内存大小不一定是物理内存大小。

    通常,您只能通过大量指纹和读取命令探测来确定

  • 指纹识别:这意味着您需要一个制造商特定特征的数据库(例如,从数据表中收集,不幸的是,更经常的是,从经验测试中收集,因为大多数标签都没有(公开?或根本没有?)记录这些信息),您可以对照这些信息检查标签

  • 探测:

    • 从第0页开始
    • 阅读页面
    • 成功时:将读取地址增加4页,然后重新开始
    • 失败时:将读取地址减1,然后再次尝试读取,直到找到可读地址
    • 在扇区结束时:从下一个扇区开始
    这样,您就可以找到最后一个可读的页面地址,它不一定是标记内存的“真实”端(例如,在端部可能有受保护的页面)

  • 如果您的Ultralight和NTAG标记是EV1标记(即,它们实现Ultralight EV1命令集),则expose a GET_VERSION命令可用于检索存储大小信息。版本信息与所有现有标签指纹数据库(您可以从Ultralight/NTAG数据表中获得该信息)相结合,将允许您可靠地1确定标签类型,从而确定内存大小

    1) 除了一些以“NTAG”出售的假冒芯片外,这些芯片模仿真实NTAG芯片的参数,但似乎内存大小、缺乏命令支持等与它们模仿参数的芯片不匹配


    当涉及到遵循NFC论坛类型2标记操作规范的NFC标记时,您还可以依赖编码到功能容器中的标记内存大小。但是,此内存大小不一定是物理内存大小。

    通常,您只能通过大量指纹和读取命令探测来确定

  • 指纹识别:这意味着您需要一个制造商特定特征的数据库(例如,从数据表中收集,不幸的是,更经常的是,从经验测试中收集,因为大多数标签都没有(公开?或根本没有?)记录这些信息),您可以对照这些信息检查标签

  • 探测:

    • 从第0页开始
    • 阅读页面
    • 成功时:将读取地址增加4页,然后重新开始
    • 失败时:将读取地址减1,然后再次尝试读取,直到找到可读地址
    • 在扇区结束时:从下一个扇区开始
    这样,您就可以找到最后一个可读的页面地址,它不一定是标记内存的“真实”端(例如,在端部可能有受保护的页面)

  • 如果您的Ultralight和NTAG标记是EV1标记(即,它们实现Ultralight EV1命令集),则expose a GET_VERSION命令可用于检索存储大小信息。版本信息与所有现有标签指纹数据库(您可以从Ultralight/NTAG数据表中获得该信息)相结合,将允许您可靠地1确定标签类型,从而确定内存大小

    1) 除了一些以“NTAG”出售的假冒芯片外,这些芯片模仿真实NTAG芯片的参数,但似乎内存大小、缺乏命令支持等与它们模仿参数的芯片不匹配

    当涉及到遵循NFC论坛类型2标记操作规范的NFC标记时,您还可以依赖编码到功能容器中的标记内存大小。该内存大小不一定是物理m
    int numberOfPages = 0;
    int tagType = ulTag.getType();
    if(tagType == MifareUltralight.TYPE_ULTRALIGHT) {
        numberOfPages = 16;
    } else if(tagType == MifareUltralight.TYPE_ULTRALIGHT_C) {
        numberOfPages = 47;
    }
    
    int totalBytes = ulTag.getMaxTransceiveLength() + 3;
    int totalPages =  totalBytes / ulTag.PAGE_SIZE;
    
    public static final int OFFSET_128_BYTE =  0x025;
    public static final int OFFSET_48_BYTE  =  0x010;
    
    public static int checkType(MifareUltralight mrfid){
        int cfgOffset = -1;
        byte[] response = null;
        byte[] writeResponse = null;
        try {
            response = mrfid.transceive(new byte[]{
                    (byte) 0x60 // GET_VERSION
            });
        } catch (TagLostException tle) {
            Utility.log("setPasswordAndEnable GET_VERSION, TagLostException ... ");
            return cfgOffset;
        } catch (IOException ioe) {
            Utility.log("setPasswordAndEnable GET_VERSION, IOException ... ");
            return cfgOffset;
        }
        if ((response != null) && (response.length >= 8)) {
            // success
            if ((response[0] == (byte) 0x00) && (response[1] == (byte) 0x04)) {
                // tag is from NXP
                if (response[2] == (byte) 0x03) {
                    // MIFARE Ultralight
                    if ((response[4] == (byte) 0x01) && (response[5] == (byte) 0x00)) {
                        // MIFARE Ultralight EV1 (V0)
                        switch (response[6]) {
                            case (byte) 0x0B:
                                // MF0UL11
                                cfgOffset = OFFSET_48_BYTE;
                                break;
                            case (byte) 0x0E:
                                // MF0UL21
                                cfgOffset = OFFSET_128_BYTE;
                                break;
    
                            default:
                                // unknown
                                break;
                        }
                    }
                }
            }
        }
        return cfgOffset;
    }