当前位置: 首页 > 面试题库 >

NFC阅读器“ SELECT(通过AID)” APDU未路由到Android设备

龚沛
2023-03-14
问题内容

我有一个安装了ACR122驱动程序的ACR122U NFC读写器连接到Windows计算机。

我尝试使用javax.smartcardioAPI将SELECT(通过AID)ADPU发送到我的Android设备(应该处于HCE模式)。

这是我的代码:

TerminalFactory factory = TerminalFactory.getDefault();
List<CardTerminal> terminals = factory.terminals().list();
CardTerminal terminal = terminals.get(0);
System.out.println(terminal.getName());
Card card = terminal.connect("*");
CardChannel channel = card.getBasicChannel();
execute(channel, new byte[] { (byte) 0xFF, 0x00, 0x51, (byte) 195, 0x00}, card);
execute(channel, new byte[] { (byte)0xFF, 0x00, 0x00, 0x00, 0x04,(byte)0xD4, 0x4A, 0x01, 0x00}, card); //InListPassiveTarget
execute(channel, new byte[] { (byte)0xFF, 0x00, 0x00, 0x00, 0x04,(byte)0xD4, 0x4A, 0x01, 0x00}, card); //InListPassiveTarget
execute(channel, new byte[] {0x00, (byte) 0xA4, 0x04, 0x00, 7,
                (byte)0xF0, 0x01, 0x02, 0x03, 0x04, (byte) 0x05, 0x07, 0}, card); //select AID

...

public static void execute(CardChannel channel, byte[] command, Card...cards) throws CardException {
    ByteBuffer r = ByteBuffer.allocate(1024);
    channel.transmit(bufferFromArray(command), r);
    System.out.println(convertBinToASCII(r.array(), 0, r.position()));
}

这是我得到的输出:

ACS ACR122 0
3B8F8001804F0CA000000306030000000000006B
C3
D54B6300
D54B010108032004010203049000

我想这01020304是我的Android设备提供给NFC阅读器的UID。SELECT APDU不返回任何响应,它的长度为0个字节。

在我的Android设备上,我有以下服务:

public class MyHostApduService extends HostApduService {

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e("APDU", "APDU service was created.");
    }

    @Override
    public byte[] processCommandApdu(byte[] apdu, Bundle extras) {
       Log.e("APDU", "command apdu: " + Arrays.toString(apdu));
       return new byte[2];
    }
    @Override
    public void onDeactivated(int reason) {
       Log.e("APDU", "ON DEACTIVATED.");
    }
}

但是processCommandAdpu没有被打电话。查看日志时,应该将SELECT
ADPU发送给阅读器时,我什么也找不到,所以似乎ADPU甚至都没有到达Android设备。

这是Android项目的apduservice.xml:

<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:description="@string/servicedesc"
    android:requireDeviceUnlock="false" >
    <aid-group
        android:category="other"
        android:description="@string/aiddescription" >
        <aid-filter android:name="F0010203040507" />
    </aid-group>
</host-apdu-service>

此外,还有一些ADPU,它们在传输时会使NFC读取器有些卡住。例如,

execute(channel, new byte[] {(byte) 0xFF, 0x00, 0x00, 0x00, 0x02, (byte) 0xd4, 0x04}, card);

用于查询PN532芯片当前状态的伪APDU,不返回任何响应。可能是这个特定的读者有缺陷吗?我该如何检查?

更新 (基于chat中的讨论):

使用第二个阅读器(相同型号,相同版本)进行的测试才起作用。因此,第一个阅读器上的设置可能有些晦涩,或者阅读器刚出现故障。

两种阅读器具有相同的版本信息:

  • ACR122U固件版本:41435231323255323135(-> ACR122U215)
  • PN532版本:D503 32010607 9000(-> PN532 v1.6)

问题答案:

您使用InListPassiveTarget直接指示ACR122U内部的PN532
NFC芯片手动轮询标签。这实际上绕过了ACR122U的抽象层,允许您自动轮询标签并使用“标准PC /
SC”与枚举的智能卡交换APDU命令。因此,无法通过PC / SC接口发送普通APDU,并且SELECT APDU将永远不会到达Android HCE端。

相反,您还需要通过直接与PN532传输模块对话来交换APDU命令。您可以通过将APDU命令包装在InDataExchange命令(或InCommunicateThru,如果您需要控制ISO
/ IEC 14443-4标头字段)中来完成此操作。在您的情况下,包装的SELECT(通过AID)命令APDU类似于:

execute(channel, new byte[] {
    (byte)0xFF, 0x00, 0x00, 0x00,  // direct PN532 command
    16,                // Lc = command length
    (byte)0xD4, 0x40,  // InDataExchange
    0x01,              // Tag #1 (equal to the tag number from the InListPassiveTarget response)
    0x00, (byte)0xA4, 0x04, 0x00,                         // APDU: SELECT (by AID)
          7,                                              // Lc = AID length
          (byte)0xF0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, // AID = F0010203040507
          0x00,                                           // Le = max
}, card);

可能是这个特定的读者有缺陷吗?

是的,尽管我对此表示怀疑,但情况可能是这样。请注意,ACR122U固件有许多不同的版本,其中大多数似乎在设计上存在缺陷。特别是以下事实:读取器的某些版本执行自动标签枚举,而某些版本不执行,并且可用API在该读取器的不同版本之间发生了巨大变化,这使得对该设备进行编程变得很困难。

更新:更多观察结果…

  • 对InListPassiveTarget命令的响应不包含ATS数据(在UID字段之后)。也许您的阅读器在标签选择期间不执行自动RATS。可以使用SetParameters命令(在InListPassiveTarget之前)启用此功能:
    execute(channel, new byte[] {
    (byte)0xFF, 0x00, 0x00, 0x00,  // direct PN532 command
    3,                 // Lc = command length
    (byte)0xD4, 0x12,  // InDataExchange
    (1<<4),            // fAutomaticRATS = 1
    

    }, card);

您也可以尝试使用InCommunicateThru手动发送RATS命令:

    execute(channel, new byte[] {
    (byte)0xFF, 0x00, 0x00, 0x00,  // direct PN532 command
    4,                 // Lc = command length
    (byte)0xD4, 0x42,  // InCommunicateThru
    (byte)0xE0, 0x80,  // RATS (FSD = 256, CID = 0)
}, card);

之后,您可以尝试使用InCommunicateThru和原始ISO / IEC 14443-4块与卡进行通信:

    execute(channel, new byte[] {
    (byte)0xFF, 0x00, 0x00, 0x00,  // direct PN532 command
    16,                // Lc = command length
    (byte)0xD4, 0x42,  // InCommunicateThru
    0x02,              // PCB (I-block, change to 0x03 for the next block)
    0x00, (byte)0xA4, 0x04, 0x00,                     // APDU: SELECT (by AID)
      7,                                              // Lc = AID length
      (byte)0xF0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, // AID = F0010203040507
      0x00,                                           // Le = max
}, card);
  • ATQA 0803看起来很奇怪。尤其是位帧防冲突字段中的0x03表示该字段中有多个目标(因为符合标准的标记只会在位帧防冲突字段中设置单个位)。 请注意,这是不正确的。 在对InListPassiveTarget的响应中,ATQA的发送顺序为低位优先。因此,位帧防冲突值是0x08(=有效/兼容),专有字段中的值是0x03。

  • 确实,您的阅读器不响应某些PN532命令是很奇怪的(特别是因为固件版本32010607看起来不错)。我已经用另一个ACR122U测试了一些对您而言失败的命令,它们已成功完成…



 类似资料:
  • 在问题[1]中,我了解到如果您想在Android下使用NFC标签,则不必采用NDEF格式。我想在Win 8.1 in. Net下执行此操作。我的情况是这样的: 我有一个RFID卡Mifare Classic 1K,其中存储了一个ID。(由制造商记录)该ID由我们的考勤系统通过通常的RFID读取器(例如Gigatek的PROMAG MFR120)读取。我们不在卡上写任何东西,我们只需要读取ID。但是

  • 我使用下面的示例代码来读取NFC标签,但它不是多次读取标签(有时读取3次,有时读取6-7次)。在我的应用程序中,我需要连续读取nfc标签。 https://github.com/andijakl/NfcDemo

  • 我有一个ACR122U NFC阅读器,正在用一个简单的文字“测试”向MIFARE Classic 1K标签的块1写入数据。 是否可以使用三星Galaxy S3读取Android系统的NFC标签?是不是有什么app可以做呢? 这是我的Windows应用程序读取标记时的日志输出:

  • 我正在尝试从2个设备(Nexus 5和Samsung S5)读取NFC标签。 我正在通过前台调度读取标记,并使用intent。在Samsung S5上,Tech列表列出了、和,但在Nexus 5上,它只列出了。 我知道Nexus 5不支持恩智浦的MIFARE Classic标签。因此,我理解了为什么它没有列出。但是为什么它也不在tech列表中显示呢? 当我尝试使用intent读取标签时,三星S5读

  • 我正在尝试从/到我的NTAG216标签读取/写入NDEF消息。 作为此开发的基础,我使用Microsoft NFC示例中的PcscSdk:https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/Nfc 我能够成功连接到卡。它被识别为Mifare Ultralight,我可以读/写上面的前16个块。如果我请

  • Android PDF Viewer 是Android平台下的PDF阅读器。