【问题标题】:Android NfcA Transceive fails on successAndroid NfcA Transceive 成功失败
【发布时间】:2014-04-12 00:34:32
【问题描述】:

我为快速调试做了一个简单的测试应用程序。我发送一些字节,在手机屏幕上打印我发送的内容并打印我收到的内容。

当我发送错误命令时,我在两个字节 SW1SW2 中得到相应的错误代码。 我也可以调用我自己的命令并用我自己的值覆盖 SW1SW2,我可以得到它们。

问题是:当我发送一个正确的命令时,收发命令失败,并出现信息异常“收发失败”。

如果我发送正确的命令,但将 SW1SW2 覆盖为 90 00 以外的值,那么我会得到我设置的 SW 值,但没有响应数据。 (可能是因为卡在SW1SW2 90 00时不发送ODATA)

那我怎么就确定我发送了正确的命令呢?除了弄乱我自己的测试命令之外,我还调用了 GetAppId 命令——它失败了,说我必须在卡中定义 AppId。 所以我在卡里定义,发送同样的命令,收发失败。

所以我很确定问题是当有 ODATA 时收发失败,但我不明白为什么或如何修复它.. 请帮助!

编辑:我的卡是 ZeitControl 的 7.5 D 非接触式基本卡。

EDIT2:我已将超时设置为 2000 毫秒,但行为没有变化。我正在尝试返回单个字节的数据,而我调用的系统命令听起来也不重。

然后我下载并附加了 Android 源代码并进行了调试。有些部分它仍然不会进入 - 但卡似乎在有效命令上返回 null ,除非我返回一些手动设置的 SW1SW2 在这种情况下,这是唯一收到的东西。

EDIT3:我尝试的系统命令是: 192 14 0 0 0 (或 C0 0E 00 00 00) (或 CLA INS P1 P2 Lc) 我不是 100% 确定我做对了,但我已经尝试了各种长度(最多 22 个)的 Le 和没有 Le 如上所述,只有没有它不会给我 6700(错误的 Le/Lc) 当然,它似乎返回 null 而不是 6700...

另一个命令是我自己定义的 20 0A(值作为字节)并且在 .BAS 文件中没有指定 P1/P2。 我称之为: 32 10 1 0 1 (或 20 0A 01 00 01) (或 CLA INS Lc IDATA Le) 这应该意味着 1 字节数据输入,设置为 0,1 字节预期输出(+ SW1/SW2 一如既往)。 (设置 P1/P2 给出 6700 所以除非在命令声明中定义,否则我认为它们不应该存在) 这也返回 null。我希望在这里返回 00 90 00。 (如果我将“值”设置为 00 即)

我正在使用 HTC One X。

编辑4: MinSdk 版本 = 14 和目标 18。

if(bitcoinCard  != null){
try {
    String sentmsg, receivedmsg;
    byte[] send = getBytes(commandBytes.getText().toString());
    byte[] data = null;
    if(send != null){
        bitcoinCard.setTimeout(2000);
        data = bitcoinCard.transceive(send);
}
        //bitcoinCard.close();
        /*if(data != null && data.length == 2)
        {
            mainLabel.setText("SW1SW2: " + (data[0] < 0 ? -data[0] + 
128 : data[0]) + " " + (data[1] < 0 ? -data[1] + 128 : data[1]));
        }else */if (data != null && send != null)
        {
            sentmsg = "" + (send[0] < 0 ? send[0] + 256 : send[0]);
            for(int i = 1; i < send.length; i++)
            {
                sentmsg = sentmsg + " " + (send[i] < 0 ? send[i] + 
256 : send[i]);
            }
            receivedmsg = "" + (data[0] < 0 ? data[0] + 256 : data[0]);
            for(int i = 1; i < data.length; i++)
            {
                receivedmsg = receivedmsg + " " + (data[i] < 0 ? data[i] + 256 : data[i]);
            }
            mainLabel.setText("Sent: " + sentmsg + "\n" +
                              "Response: " + 
receivedmsg);
        }else
        {
            mainLabel.setText("Sent or received null.");
        }
    } catch (IOException e) {

        mainLabel.setText("Tried to talk to card, but had error: " + 
e.getMessage());
    }   
}

【问题讨论】:

  • 如果我们知道您使用的是什么类型的卡/NFC 标签可能会有所帮助。
  • 这是 7.5 D 非接触式基本卡。有没有什么地方可以得到更多关于安卓收发功能或如何调试的信息?
  • 您可以检查是否遇到超时情况。在这种情况下,错误的命令会很快返回,但卡上的操作可能需要比 NFC 堆栈等待标签响应的时间更长。在这种情况下,通过 setTimeout(int timeout) 增加超时值可能会有所帮助。
  • @corvairjo 见edit2。
  • 你发送什么命令?你发送/期望/得到什么回应?您使用的是什么 Android 设备?

标签: android nfc apdu contactless-smartcard


【解决方案1】:

首先,当您发送 APDU 时,您应该使用 IsoDep 对象(而不是 NfcA)。 Android 应将这两种标签技术都显示为您的卡可用。这里的问题是,如果您使用IsoDep,Android 通常只会在 ISO 14443-4 协议模式下激活卡。因此,如果使用NfcA,您的卡将无法接受 APDU。

我刚刚测试过,至少在装有 Android 4.1.2 的 Nexus S 上是这种情况。事实上,尝试使用 NfcA 对象进行收发会导致 TagLostExceptions 使用某些卡,而我尝试使用的另一张卡会导致其他一些非常奇怪的行为。

其次,如果你发送

byte[] cmd = { (byte)0xC0, (byte)0x0E, (byte)0x00, (byte)0x00, (byte)0x00 };

我希望卡返回实际的应用程序 ID。但是,此命令的答案(即&lt;data&gt; &lt;SW1=61&gt; &lt;SW2=len&gt;)不符合 ISO 7816-4(对于 61xx 状态代码不应返回任何数据),因此这可能会导致问题。

更新:我刚刚使用 Nexus S (Android 4.1.2) 进行了测试,收到这样的响应没有问题。

最后,您的其他命令 (20 0A) 不是您所期望的:

  1. 我强烈建议您只使用设置为0x000x80 的CLA 字节,除非您知道自己在做什么(使用安全消息传递、使用逻辑通道......)。虽然,Android(至少使用 NXP 的 NFC 芯片组)并不关心 APDU 的结构,但您的卡可能会!
  2. APDU 的格式始终为&lt;CLA&gt; &lt;INS&gt; &lt;P1&gt; &lt;P2&gt; [Lc [DATA]] &lt;Le&gt;(特殊情况为&lt;CLA&gt; &lt;INS&gt; &lt;P1&gt; &lt;P2&gt;)。所以这意味着您不能简单地省略 P1 和 P2。
  3. 您是正确的,如果 SW9000 和 SW161,BasicCard 将丢弃 ODATA。

【讨论】:

  • 我不知道 IsoDep 与 NfcA 的区别,它似乎没有区别,而且该卡专门是 NfcA,而 IsoDep 是基于 NfcA/NfcB 构建的。 ZC 手册中关于 CLA 字节的唯一内容是 C0 是为 ZC 命令保留的。他们自己的示例使用 20 表示 CLA ......所以我对此很生气,但只需将 CLA 更改为 80 就可以了。我不知道为什么我之前可以返回我自己的 SW1/SW2.. 可能是 android 手机做了什么或者我正在重新定义另一个命令。
  • (将 CLA 更改为 80 也使卡再次需要 P1/P2。)
  • 更新:我写道 IsoDep 与 NfcA 没有区别。我不知道为什么,但是当我上次测试时,情况确实如此。然而,现在它似乎确实有所作为。您必须使用 IsoDep。
猜你喜欢
  • 2019-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-14
  • 2018-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多