通过javax.smartcardio读取幻影NFC标签



我有一个旧的 NFC 阅读器,用于 tikitag Web 服务(后来更名为 touchatag,最终在 2012 年左右被废弃(。由于该网站不再可用,我无法再找到原始的tikitag/touchatag驱动程序。经过一番搜索,我发现这个NFC读卡器是一个通用的ACS ACR122U USB读卡器,并从这里安装了合适的驱动程序。我的系统是Windows 7(64位(。

首先,我尝试了NFC工具库,以便对NFC标签进行高级读写访问。我收到一条错误消息,指出遇到不受支持的标签;尽管阅读器上没有标签,甚至在附近也没有标签。似乎其他开发人员也在此库中遇到了相同的错误,如下所示。请注意,此标记是无限次检测到的(因此,它不会在检测到一次后消失(。

我将所需的低级代码复制到一个单独的类中(即独立于NFC工具库(。您可以在下面找到此代码(类似的代码也可以在教程中找到(:

import java.util.List;
import javax.smartcardio.Card;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.TerminalFactory;
import org.nfctools.utils.NfcUtils;
public class NdefTest {
    public static void main(String[] args) throws Exception {
        TerminalFactory factory = TerminalFactory.getDefault();
        List<CardTerminal> terminals = factory.terminals().list();
        CardTerminal terminal = terminals.get(0);
        if (terminal.waitForCardPresent(5000)) {
            Card card = terminal.connect("T=0");
            System.out.println(NfcUtils.convertBinToASCII(card.getATR().getHistoricalBytes()));
        }
    }
}

此代码检测与使用 NFC 工具库时完全相同的"幻像"标签。因此,此问题似乎与 NFC 工具库无关(正如库开发人员在响应错误报告时所暗示的那样(。要么我错过了一些东西,要么问题与安装的驱动程序、NFC 读卡器硬件或 javax.smartcardio 中的一些未修复的错误有关(按可能性顺序列出(。

我尝试卸载上述驱动程序并让Windows 7自行安装合适的驱动程序(称为"Microsoft Usbccid智能卡读卡器(WUDF("(,这会导致与上述相同的错误。我没有尝试过其他阅读器,因为我只有一个。

(注意:在Windows设备概述中,此NFC读卡器的名称是"CCID USB读卡器",而不是"ACS ACR122"或相关名称。不知道这是否重要,只是想我会提到它。

有没有人遇到过这个问题,并设法解决了它?

更新

好的,我尝试在检测到模拟标签后向阅读器发送CLF命令;即获取连接的PICC的ATS(ACR122U手册第11页(:

TerminalFactory factory = TerminalFactory.getDefault();
List<CardTerminal> terminals = factory.terminals().list();
// (this is the correct terminal)
CardTerminal terminal = terminals.get(0);
if (terminal.waitForCardPresent(5000)) {
    Card card = terminal.connect("*");
    CardChannel channel = card.getBasicChannel();
// (I tried both 0x00 and 0x01 as P1, as well as 0x05 for Le)
    CommandAPDU getAts = new CommandAPDU(0xFF, 0xCA, 0x00, 0x00, 0x04);
    ResponseAPDU response = channel.transmit(getAts);
    System.out.println(response.getSW1());
    System.out.println(response.getSW2());
}

但是我不断收到错误响应代码(0x63 0x00(。关于我可能做错了什么的任何想法?

您遇到的问题是此版本的ACR122U读取器以某种非标准的方式使用 PC/SC (CCID(。

使用 PC/SC

API 检测的"卡"实际上是由读卡器模拟的虚拟卡(即使没有卡也允许 PC/SC API 打开连接(或读卡器SAM插槽中的智能卡芯片(读卡器外壳内存在的接触卡(。

无论哪种情况,该读卡器仅使用PC/SC作为该读卡器中使用的非接触式前端芯片的本机命令的传输协议(恩智浦PN532(。因此,如果要使用读取器的非接触式功能,则必须使用CLF的本机命令集。有关更多详细信息,请参阅 ACR122U API 文档或 libnfc 实现。

(所有的功劳都归功于Michael Roland;这篇文章旨在作为解决方案摘要(

好的迈克尔,鉴于您上一条评论中的示例,我终于明白您使用PC/SC协议通过隧道CLF命令是什么意思。我测试了 PN532 文档中的一些命令,它们返回有效结果。(但是,您作为示例给出的命令不起作用并导致读取器崩溃;必须重置它。

例如,要获取固件版本:

CommandAPDU commApdu = new CommandAPDU(0xFF, 0x00, 0x00, 0x00, 
    new byte[] { (byte)0xD4, (byte)0x02 });

InDataExchange 命令:

CommandAPDU commApdu = new CommandAPDU(0xFF, 0x00, 0x00, 0x00, 
    new byte[] { (byte)0xD4, (byte)0x40, 0x01 });

我找到了NFCIP库,它支持使用InDataExchange命令在对等方之间发送字节数组(例如ACS ACR122和诺基亚6131(。在阅读 PN532 文档(第 131 页(时,此命令似乎也允许读取标签。Michael,您是否碰巧知道任何处理使用这些低级命令以读取(不同类型的(标签为目标的库?

最新更新