【问题标题】:How to programmatically detect the memory size/page number of an NFC chip如何以编程方式检测 NFC 芯片的内存大小/页码
【发布时间】:2015-02-20 11:01:14
【问题描述】:

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

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

【问题讨论】:

    标签: tags nfc rfid mifare fingerprinting


    【解决方案1】:

    通常,您只能通过广泛的指纹识别和使用读取命令进行探测来确定这一点。

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

    2. 探测:

      • 从第 0 页开始
      • 阅读页面
      • 成功时:将读取地址增加 4 页并重新开始
      • 失败时:将读取地址减 1 并尝试再次读取,直到找到可读地址
      • 在扇区结束时:从下一个扇区重新开始

      这样你就可以找到最后一个可读的页面地址,它不一定是标签内存的“真实”末端(例如,末端可能有受保护的页面)。

    如果您的 Ultralight 和 NTAG 标签是 EV1 标签(即它们实现了 Ultralight EV1 命令集),请公开一个 GET_VERSION 命令,您可以使用它来检索存储大小信息。版本信息与所有现有标签指纹的数据库相结合(您可以从 Ultraight/NTAG 数据表中获取该信息)将允许您可靠地1确定标签类型,从而确定内存大小.

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

    对于遵循 NFC Forum Type 2 标签操作规范的 NFC 标签,您还可以依赖编码到功能容器中的标签内存大小。不过,此内存大小不一定是物理内存大小。

    【讨论】:

      【解决方案2】:

      我认为,从接受的答案来看,下面的代码是有意义的,

      int numberOfPages = 0;
      int tagType = ulTag.getType();
      if(tagType == MifareUltralight.TYPE_ULTRALIGHT) {
          numberOfPages = 16;
      } else if(tagType == MifareUltralight.TYPE_ULTRALIGHT_C) {
          numberOfPages = 47;
      }
      

      getMaxTransceiveLength() 用于检索使用 transceive(byte[]) 可以发送的最大字节数。 收发命令分别使用前 3 个字节作为标志、命令和页码。

      我们需要检查下面的代码是否工作?

      int totalBytes = ulTag.getMaxTransceiveLength() + 3;
      int totalPages =  totalBytes / ulTag.PAGE_SIZE;
      

      【讨论】:

        【解决方案3】:

        对于 MIFARE ULTRALIGHT,您可以通过这种方式检查版本。

        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;
        }
        

        【讨论】:

          猜你喜欢
          • 2012-10-16
          • 1970-01-01
          • 1970-01-01
          • 2020-11-01
          • 1970-01-01
          • 2011-05-15
          • 1970-01-01
          • 2011-03-22
          • 2014-01-13
          相关资源
          最近更新 更多