java – NFC阅读器“SELECT(通过AID)”APDU不会路由到Android设备
作者:互联网
我有一台ACR122U NFC读写器连接到安装了ACR122驱动程序的Windows机器.
我尝试使用javax.smartcardio API将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,不会返回任何响应.难道这个特定的读者有缺陷吗?我怎么检查呢?
更新(基于discussion in 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命令.您可以通过在InDataExchange命令中包装APDU命令来实现此目的(如果需要控制ISO / IEC 14443-4标头字段,则可以使用InCommunicateThru).在您的情况下,包装的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是以little endian传输的.因此,位帧防冲突值为0x08(=有效/兼容),并且专有字段中的值为0x03.
>确实,您的读者对某些PN532命令没有响应(特别是因为固件版本32010607看起来很好),这确实很奇怪.我用另一台ACR122U测试了一些失败的命令,并且它们成功完成了……
标签:java,nfc,apdu,hce,acr122 来源: https://codeday.me/bug/20190701/1347056.html