通过javax.smartcardio阅读幻像NFC标签

时间:2013-10-05 16:15:48

标签: java nfc smartcard smartcard-reader contactless-smartcard

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

首先,我尝试使用NFC Tools library对NFC标签进行高级读写访问。我收到一个错误,说遇到了不支持的标签;虽然阅读器上没有标签,甚至附近也没有标签。似乎其他开发人员也遇到了与此库相同的错误,如here所示。请注意,此标记无限期地被检测到(因此,它不会在被检测到一次后消失)。

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

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 Reader”,而不是“ACS ACR122”或相关的东西。不知道这是否重要,只是想我会提到它。 )。

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

更新

好的,我已经尝试在检测到模拟标签后向阅读器发送CLF命令;即,获取连接的PICC的ATS(ACR122U manual的第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)。关于我可能做错的任何想法?

2 个答案:

答案 0 :(得分:2)

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

您使用PC / SC API检测到的“卡”实际上是读卡器模拟的虚拟卡(即使没有卡也允许PC / SC API打开连接)或智能卡芯片读卡器的SAM插槽(读卡器外壳内的接触卡)。

在任何一种情况下,此阅读器仅将PC / SC用作本阅读器(NXP PN532)中使用的非接触式前端芯片的本机命令的传输协议。因此,如果要使用阅读器的非接触式功能,则必须使用CLF的本机命令集。有关详细信息,请参阅ACR122U API documentationlibnfc实施。

答案 1 :(得分:1)

(所有功劳归于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 library,它支持使用InDataExchange命令在对等体之间发送字节数组(例如ACS ACR122和Nokia 6131)。阅读PN532文档(p.131)时,似乎此命令也允许读取标签。 Michael,您是否碰巧知道任何处理的库使用这些低级命令,目标是读取(不同类型的)标签