android - 通过 Android USB 主机与智能卡读卡器通信

标签 android usb smartcard smartcard-reader pcsc

我正在尝试向智能卡发送命令。我用 Gemalto IDBridge CT30 (PC TWIN reader)和一个 IDBridge K30通过 USB 连接到 Android 设备。

我尝试通过 USB 发送 SELECT APDU 命令:

boolean claim = openedConnection.claimInterface(usbInterface, true);
byte[] data = new byte[]{
        (byte) 0x00, (byte) 0xA4, (byte) 0x04, (byte) 0x0C,
        (byte) 0x07, (byte) 0xA0, (byte) 0x00, (byte) 0x00,
        (byte) 0x01, (byte) 0x18, (byte) 0x45, (byte) 0x4E};

之后我收到了回复:

final int dataTransferred = this.openedConnection.bulkTransfer(endPointOut, data, data.length, TIMEOUT_MS);
if(!(dataTransferred == 0 || dataTransferred == data.length)) {
    throw new Exception("Error durring sending command [" + dataTransferred + " ; " + data.length + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}

final byte[] responseBuffer = new byte[endPointIn.getMaxPacketSize()];
final int dataTransferred = this.openedConnection.bulkTransfer(this.endPointIn, responseBuffer, responseBuffer.length, TIMEOUT_MS);
Console.writeLine("USB Retrieve: " + dataTransferred + " " + responseBuffer.length);
if(dataTransferred >= 0){
    return responseBuffer;
}
throw new Exception("Error durring receinving response [" + dataTransferred + "]");

答案是

0x00 0x00 0x00 0x00 0x00 0xA0 0x00 0x41 0x03 0x00

但是,根据 test project here,我应该得到 0x90 0x00 的答案.

我做错了什么?有谁能够帮我?我使用正确的方法吗?我没有使用 javax.smartcardio 的默认包类。我直接使用 USB 接口(interface)类(例如 UsbDevice)。

最佳答案

您的阅读器设备通过 USB 接口(interface)读取 CCID。您不能简单地通过批量输出端点发送 APDU(智能卡命令)并期望通过批量输入端点接收响应 APDU。相反,您需要实现 CCID 设备类协议(protocol)(请参阅 USB Device Class Specifications)。步骤是这样的:

  1. 发送 PC_to_RDR_IccPowerOn 命令激活卡。
    62 00000000 00 00 00 0000 
    |  |        |  |  |  |    |
    |  |        |  |  |  |    \--> Empty data field
    |  |        |  |  |  \-------> Unused, set to 0x0000
    |  |        |  |  \----------> Power select: 0x00 indicates automatic selection
    |  |        |  \-------------> Sequence number (increment for each command)
    |  |        \----------------> Slot number (seems to be zero for your device)
    |  \-------------------------> Length of data field (LSB first)
    \----------------------------> Message type: 0x62 indicates PC_to_RDR_IccPowerOn
    
  2. 通过 RDR_to_PC_DataBlock 接收 ATR。
    80 18000000 00 00 00 00 00 3BBF11008131FE45455041000000000000000000000000F1 
    |  |        |  |  |  |  |  |
    |  |        |  |  |  |  |  \--> Data field: ATR
    |  |        |  |  |  |  \-----> Level parameter
    |  |        |  |  |  \--------> Error register (should be zero on success)
    |  |        |  |  \-----------> Status register (should be zero on success)
    |  |        |  \--------------> Sequence number (matches the sequence number of the command)
    |  |        \-----------------> Slot number (matches the slot number of the command)
    |  \--------------------------> Length of data field (LSB first)
    \-----------------------------> Message type: 0x80 indicates RDR_to_PC_DataBlock
    
  3. 发送包装到 PC_to_RDR_XfrBlock 命令中的命令 APDU
    6F 0C000000 00 01 00 0000 00A4040C07A000000118454E
    |  |        |  |  |  |    |
    |  |        |  |  |  |    \--> Data field: Command APDU
    |  |        |  |  |  \-------> Level parameter (0x0000 for normal length APDUs)
    |  |        |  |  \----------> Block waiting timeout
    |  |        |  \-------------> Sequence number (increment for each command)
    |  |        \----------------> Slot number (seems to be zero for your device)
    |  \-------------------------> Length of data field (LSB first)
    \----------------------------> Message type: 0x6F indicates PC_to_RDR_XfrBlock
    
  4. 通过 RDR_to_PC_DataBlock 接收响应 APDU。
    80 02000000 00 01 00 00 00 9000 
    |  |        |  |  |  |  |  |
    |  |        |  |  |  |  |  \--> Data field: Response APDU
    |  |        |  |  |  |  \-----> Level parameter
    |  |        |  |  |  \--------> Error register (should be zero on success)
    |  |        |  |  \-----------> Status register (should be zero on success)
    |  |        |  \--------------> Sequence number (matches the sequence number of the command)
    |  |        \-----------------> Slot number (matches the slot number of the command)
    |  \--------------------------> Length of data field (LSB first)
    \-----------------------------> Message type: 0x80 indicates RDR_to_PC_DataBlock
    
  5. 对每个 APDU 交换重复步骤 3 和 4(不要忘记增加序列号)。

由于 ATR 指示 T=1 作为第一个协议(protocol),您可能需要将 APDU 包装到 T=1 TPDU(取决于阅读器配置)。第一个 APDU 的 I block 看起来像这样:

00 00 0C 00A4040C07A000000118454E 15
|  |  |  |                        |
|  |  |  |                        \--> LRC (due to missing TC in ATR): XOR checksum over all other bytes
|  |  |  \---------------------------> INF: APDU
|  |  \------------------------------> LEN: length of INF field
|  \---------------------------------> PCB: toggle between 0x00 and 0x40 for every other I-block
\------------------------------------> NAD: node addressing

所以你的 PC_to_RDR_XfrBlock 命令看起来像:

6F 10000000 00 01 00 0000  00 00 0C 00A4040C07A000000118454E 15

然后您会收到包裹在 I-block 或 R- 或 S-block 中的答案,表明需要进行一些特殊/错误处理。

关于android - 通过 Android USB 主机与智能卡读卡器通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40975868/

相关文章:

android - 市场安装应用后点击通知会触发什么Intent?

未检测到 Linux USB 设备驱动程序

android - 如何让Android手机充当非接触式智能卡?

android - ISO 14443 A 类卡读/写使用 Android

tomcat - 尝试使用智能卡向 Tomcat 进行身份验证

android - XMLPullParser,如何从一个标签获取多个值,android

android - admob 广告在签名的 apk 中不起作用,它在调试版本中完美运行

c# - 从二进制文件读取字符串,不同的编码

connection - HTC Desire 与 Ubuntu 10.04 的 USB 连接问题

android - 在 Android 9 上绕过 android usb 主机权限确认对话框