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

use*_*777 7 usb android smartcard pcsc smartcard-reader

我正在尝试向智能卡发送命令.我使用Gemalto IDBridge CT30(PC TWIN阅读器)和通过USB连接到Android设备的IDBridge K30.

我尝试通过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};
Run Code Online (Sandbox Code Playgroud)

之后我收到了答案:

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 + "]");
Run Code Online (Sandbox Code Playgroud)

答案是

0x00 0x00 0x00 0x00 0x00 0xA0 0x00 0x41 0x03 0x00
Run Code Online (Sandbox Code Playgroud)

但是,我应该0x90 0x00根据这里测试项目得到答案.

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

Mic*_*and 10

您的读卡器设备通过USB接口说出CCID.您不能简单地通过批量输出端点发送APDU(智能卡命令),并期望通过批量输入端点接收响应APDU.相反,您需要实现CCID设备类协议(请参阅USB设备类规范).步骤如下:

  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. 发送命令APDU包装到PC_to_RDR_XfrBlock命令中
    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作为第一个协议,因此您可能需要将APDU包装成T = 1个TPDU(取决于读取器配置).第一个APDU的I块看起来像:

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块或R块或S块中的答案,表明需要进行一些特殊/错误处理.


gui*_*dot 0

您发送的是一个带有给定 AID 的 SELECT 命令,它很容易产生结果。但是,您明确表示您对回复不感兴趣,通过

  • 将 P2 设置为“0C”
  • 不提供 LE 字节(假设基于块的协议,对于 USB 来说肯定是合理的)

因此,人们可能会得出这样的结论:您的卡不符合 ISO 7816-4;另一方面,响应也不包含任何看起来像错误 SW1/SW2 状态的内容,您确定要转储响应缓冲区吗?