【问题标题】:Android NFC tag ID identify different nfc card typeAndroid NFC 标签 ID 识别不同的 NFC 卡类型
【发布时间】:2020-10-23 09:36:42
【问题描述】:

我想在我的应用程序中使用 NFC 读取,我在其中读取 NFC 卡的 ID。 我有 2 张不同的 NFC 卡。 当我用电脑中的 USB NFC 阅读器读取它们时,我得到两张卡的 9 位数字,这很酷。我可以根据那个数字识别卡片。

当我想在我的应用程序中阅读它们时,就会出现问题,如下所示:

                            new NfcAdapter.ReaderCallback() {
                                @Override
                                public void onTagDiscovered( final Tag tag ) {
                                    runOnUiThread(new Runnable() {

                                        @Override
                                        public void run() {
                                            System.out.println(tag.toString());

                                            // I get the ID here to identify the card
                                            String id = Long.toString(Utils.toDec(tag.getId())).trim();
                                        }
                                    });

                                }
                            },
                            1 | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK,
                            options);

当我记录发现的 TAG 的 toString() 方法时,我得到了第一张卡片:

Tech [android.nfc.tech.NfcA, android.nfc.tech.MifareClassic]

当我阅读下面的 ID String id = Long.toString(Utils.toDec(tag.getId())).trim(); 时,我得到了与我电脑中相同的 9 位数字,这很好,这是卡的唯一 ID。

第二张卡片的toString()

Tech [android.nfc.tech.IsoDep, android.nfc.tech.NfcA]

当我读取标签 ID 时,我得到一个 17 位数字而不是 9 位数字... 我试图在发现的 TAG 中记录所有内容,但我找不到可以通过 USB 读卡器从计算机中读取的那张卡的 9 位数字。所以我无法识别这张 NFC 卡。

我该如何解决这个问题?我想通过 USB 读卡器和我的应用程序来识别卡,所以这两个数字必须相同,就像第一张卡一样...

谢谢! :)

【问题讨论】:

  • 卡的品牌和型号是什么,ID较长,因为某些卡出于兼容性原因有多个长度ID。
  • 没问题,如果第二张卡有更长的ID,但是当我通过计算机中的USB读卡器读取它时,我没有得到这个更长的ID,而是一个更短的9位数字......所以我的 PC 和 Android 应用程序中的 USB 阅读器中没有完全相同的唯一 ID...
  • 在不知道卡的品牌和型号的情况下,我无法告诉您如何在 USB 读卡器和 Android 手机上读取短版或长版。

标签: android nfc rfid


【解决方案1】:

因此,根据其数据表 https://www.nxp.com/docs/en/data-sheet/MF3DX2_MF3DHX2_SDS.pdf 的第 7.4 节(以及亚马逊列表),此卡的 UID 是 7 字节 UID

所以它不是一张为了兼容而具有多个 ID 的卡,但它使用的标准确实允许 4、7、10 字节的 UID 请参阅标准的第 19 页http://emutag.com/iso/14443-3.pdf

根据 ISO 1444-3 标准,较大的 UID 在多个部分和数据表中发送

根据 ISO/IEC 14443-3 在第一个防冲突循环期间,级联标签返回值 88h 以及 UID 的前 3 个字节,UID0 到 UID2 和 BCC。第二个防冲突循环返回字节 UID3 到 UID6 和 BCC

流程说明,问题说明在应用笔记https://www.nxp.com/docs/en/application-note/AN10927.pdf

所以在应用笔记第 3.2 节中

在某些情况下,阅读器基础架构可能能够处理双倍大小的 UID,但(后台)系统只能处理 4 字节的 UID。反之亦然,阅读器基础架构可能无法处理 Double Size UID,但(背景)系统需要唯一性并且可以处理 Double Size UID。

因此,USB 读卡器和运行它的代码可能会做防冲突错误,因为它无法处理超过它返回的 4 字节 UID,它可能没有响应卡返回的数据并处理级联标记位(因此它实际上可能只返回 7 字节 UID 的前 3 个字节。

您没有提供使用的 USB 阅读器(品牌和型号)或用于读取它的源代码或应用程序的详细信息,因此无法帮助查看它是否可以返回正确大小的 UID。

但应用说明附录 6 提供了将 7 字节 UID 转换为 4 字节 UID 的代码(不幸的是,这是在 C 而非 Java 中,但您应该能够将其转换为 Java)但 USB 阅读器可能会返回正确的也是 4 字节的 UID,所以这可能无济于事。

此外,为了更好地诊断,将值打印为十六进制而不是十进制,因为这样可以更好地告诉您正在发生的事情。

已添加
一种将字节数组转换为可打印十六进制字符串的方法https://stackoverflow.com/a/332101/2373819

此外,如果您提供更多信息以及卡中的实际 UID 值,则可能会看到 USB 读卡器出了什么问题(即 UID 的第一个字节是 88h 吗?)

更新说明 其他卡很容易看出它是 Mifare Classic,像 EV1 这样的新版本也有 7 字节 UID(非常旧的型号有 4 字节 UID)所以也应该显示更大的十进制 UID(如果像 EV1 版本这样的现代卡) 但是这也有一个 4 字节的 UID 作为 7 个字节中的前 4 个字节,以与旧版本兼容。

因为您正在使用通用标记技术类型读取 UID,它可能会将其截断为 4 个字节,或者它可能是旧版本。在使用 getID 之前尝试在正确的特定类中获取标签,例如

MifareClassic mMifareClassic = MifareClassic.get(tag);
byte[] uid = mMifareClassic.getID();

您可以使用开关tag.getTechList(); 为每种类型的标签使用正确的标签技术类

或者尝试阅读Block 0直接获取UID。

总结
问题是当卡只有 NXP Mifare Desfire 卡的 7 字节 UID 时,USB 读卡器给出的似乎是 4 字节 UID。

在 MifareClassic 卡上,它应该是 7 字节 UID 的前 4 个字节,因为新的 7 字节 UID 卡旨在与旧的 4 字节 UID 卡兼容,因此您可以将数组的一部分用于让他们匹配。

在 NXP Mifare Desfire 卡上

A) 第一个防冲突命令的 4 个字节? (这将包括级联标记 88h 值)

B) 7 字节 UID 的前 4 字节?所以你可以再切一片让它们匹配。

注意
这些值的某些表示首先给出最高有效位而不是最低有效位。

例如,从您的 cmets 中,其中一个长 UID 是十进制的 36125410196403972,即十六进制的 8057DE821F3704,但数据表中说最低有效字节应该是 04,将 NXP 标识为制造商,但您可以从 8057DE821F37 中看到04 颠倒过来,因为最高有效位在前,最低有效位在最后。

因此,您可以尝试使用前 4 个字节的组合进行试验,看看是否可以让它们全部匹配。

或者让 USB 阅读器为两张卡读取正确的完整 7 字节 UID(因为仅使用 4 字节并不能保证唯一性(即使是 7 字节 UID 或任何大小的 UID 也不应该用于唯一性和安全性,因为它们太容易伪造了))

【讨论】:

  • 感谢您的详细解答! :) 当我通过 PC 中的 USB 读卡器读取卡时,我得到这个:2183ö8378ö 在将 getId() 转换为十进制后的 android 上,我得到这个:36125410196403972 但原始 tag.getId() 是这样的:[B@72e0c8f我也尝试过这样的日志记录,但NfcAIsoDepMirafeClassic 中没有getId() 方法。如果没有MifareClassic,我如何阅读Block0
  • 有趣的是,当我登录 techList 时,没有 MifareClassic..android.nfc.tech.IsoDep android.nfc.tech.NfcA 第一张卡有MifaceClassic,它可以通过 android 和 USB 读卡器正常工作。另一张卡没有MifareClassic,只有IsoDepNfcA。我不在乎 id 有多少个字符,但我想在我的电脑上用 android 或 usb 阅读器阅读时获得相同的 id。
  • 这两张卡看起来像 2 种不同的品牌和型号,因此符合不同的标准,因此表现也不同。我添加了如何更好地将字节数组转换为可打印的十六进制字符串
  • 所以IsoDep 卡没有与MifareClassic 上的Block 0 等效的内容,因为它的结构和存储数据的方式根本不同。比较这些值的另一个问题是字节排序方向,例如36125410196403972 是十六进制的 8057DE821F3704,但数据表中说最低有效字节应该是 04,将 NXP 标识为制造商,但正如您从 8057DE821F3704 中看到的那样,它被反转为最高有效位。
猜你喜欢
  • 2020-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-13
相关资源
最近更新 更多