如何为读卡器获取基于主机的卡模拟应用标识(AID)

16

我正在尝试使用ACR1281U NFC标签阅读器,在Android设备上使用示例进行主机卡模拟

是我想要制作的应用程序类型。

根据Android文档和示例,需要在Android项目中注册AID:

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

我该如何确定在我的Android应用中需要注册哪个AID,以便读取HCE Android应用程序?

这是我发的另一个相关问题: 未找到支持的卡终端 ARC1281U nfc卡阅读器

我已经参考了以下链接,但并没有太大帮助:

请帮忙,因为关于HCE的资源非常少!
编辑:
示例在SELECT(按AID)命令中使用AID F0010203040506,但我的ACR128读卡器无法读取HCE设备。
private static final byte[] CLA_INS_P1_P2 = { 0x00, (byte)0xA4, 0x04, 0x00 };
private static final byte[] AID_ANDROID = { (byte)0xF0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };

private byte[] createSelectAidApdu(byte[] aid) {
    byte[] result = new byte[6 + aid.length];
    System.arraycopy(CLA_INS_P1_P2, 0, result, 0, CLA_INS_P1_P2.length);
    result[4] = (byte)aid.length;
    System.arraycopy(aid, 0, result, 5, aid.length);
    result[result.length - 1] = 0;
    return result;
}

然后我将AID更改为F00000000A0101(这是其他示例应用程序使用的),并在AID过滤器中使用它。更改为此AID后,ACR读卡器能够检测到HCE设备。

  • 这两个AID(一个在example中使用但未起作用,另一个在app中使用且有效)都符合规范,我如何知道该使用哪个AID?
  • 示例在AID过滤器中添加了多个AID,但仅发送其中一个AID的SELECT(按AID选择)APDU。我是否也应在AID过滤器中添加多个AID?它有什么用处?
1个回答

29
AID 是您为智能卡应用(在 HCE 的情况下为模拟卡应用的 Android 应用程序)分配的名称。读取器应用程序使用此“名称”通过 SELECT(按 DF 名称/AID)APDU 命令(请参阅 ISO/IEC 7816-4)来寻址您的卡(HCE)应用程序。只要符合 ISO/IEC 7816-4,您可以使用任何值。在您的具体情况中,读卡器示例应用程序 使用 AID F0010203040506
private static final byte[] AID_ANDROID = { (byte)0xF0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
因此,为了与该示例实现互操作性,您需要为AID F0010203040506 注册您的HCE服务。
如何分配和使用AID?
通常,您首先要为您的HCE应用程序定义一个“名称”。
<host-apdu-service ...>
    <aid-group ...>
        <aid-filter android:name="F0010203040506"/>
    </aid-group>
</host-apdu-service>

稍后,读卡器应用程序可以使用该名称选择您的HCE应用程序,并与其通信(例如,在Java中使用Java智能卡IO):

Card card = ...;
CardChannel c = card.getBasicChannel();

// SELECT by AID (F0010203040506)
ResponseAPDU  resp = c.transmit(new CommandAPDU(
        0x00, 0xA4, 0x04, 0x00, new byte[] { (byte)0xF0, (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, (byte)0x05, (byte)0x06 }));
assert resp.getSW() == 0x9000;

// Send application-specific command (what such a command could look like depends on your application)
resp = c.transmit(new CommandAPDU(
        0x80, 0x10, 0x00, 0x00, new byte[] { (byte)0x12, (byte)0x34 }));

如何为AID确定一个值?

这取决于您的应用场景。

  • 在您的闭环场景中,您全面控制HCE端和读卡器端,可以选择任意值 (注意有一些 AIDs的规则) 的AID,并将其分配给您的HCE应用程序。稍后您可以在读卡器应用程序中使用该AID来寻址HCE应用程序。

  • 在现实世界的HCE场景中,通常设计您的HCE应用程序与现有的读卡器基础设施进行交互。因此,您的HCE应用程序将实现某些给定的规范。在这种情况下,这样的规范将指定HCE应用程序需要使用的AID(或几个AID)以便被现有的读卡器基础设施发现。这样的规范的一个例子是EMV接触式支付系统的规范。

为什么有些HCE应用程序注册了多个AID?

有时候需要通过多个“名称”(AID)对应一个应用程序。原因可能包括:

  • 一个应用程序提供多个不同的接口(即具有不同的命令集或提供不同的数据)。
  • 存在使用不同AID(出于某种原因)来寻址同一应用程序的读卡器。

如何选择AID?

智能卡应用程序标识符(AID)的规则在ISO/IEC 7816-4中定义。一个AID至少有5个字节,最多可以由16个字节组成 (请参见这个答案关于AID大小限制)。根据前4位,AID被分成不同的组。在ISO/IEC 7816-4中定义的最相关的组是:

  • 'A'开头的AID: 国际注册的AID
  • 'D'开头的AID: 国家注册的AID
  • 'F'开头的AID: 专有AID(未注册)

对于(国际)注册的AID,AID分为两部分: 一个5字节的必备RID(注册应用程序提供商标识符)和一个可选的PIX(专有应用程序标识符扩展),长度最长为11字节。

对于专有AIDs(F...),您可以使用任意值。

为什么AID F00000000A0101可用而F0010203040506不可用?

我不知道,您没有提供足够的信息来诊断这个问题。例如,当您尝试选择F0010203040506时,在adb日志中是否有任何消息?

无论如何,两个AID都是有效的,应该都可以使用。一个可能性是您的设备上已经安装了另一个注册此AID的HCE应用程序。在这种情况下,两个应用程序将侦听同一名称,这是不可能的。


谢谢,请你帮忙回答我在编辑中添加的疑问,因为你提到的AID没有起作用。 - Rachita Nanda
1
@Michael:当你说AID应该分配给你的应用程序时,你是指在手机上运行的Android应用程序,预期模拟卡片,还是指应该将AID分配给持续读取RFID卡的窗口应用程序或其他什么东西? - Shantanu Gupta
@MichaelRoland:我指的是将AID分配给窗口应用程序。我无法弄清楚。但是有了你的代码,我会尝试研究所有可能性。 - Shantanu Gupta
@MichaelRoland:这是否意味着我需要从读卡器应用程序广播AID,已在Android OS中注册的Android应用程序将接收由读卡器应用程序广播的数据包。我的理解正确吗? - Shantanu Gupta
@SaurabhPadwekar 看起来是一个有效的AID,应该可以在AID过滤器中使用。不过我不确定你所说的“current AID”是什么意思。 - Michael Roland
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接