Android Java中USB智能卡APDU命令发送成功但响应读取异常咨询
USB智能卡读卡器APDU读取响应异常排查
问题描述
使用Android的UsbManager实现向USB智能卡读卡器发送和读取APDU命令,发送命令功能正常,但读取响应时数据不正确。需要发送的APDU命令为{0x00, (byte) 0x83, 0x00, 0x00, 0X00},上电(powerOn)和下电(powerOff)命令均可正常执行。
发送命令代码
byte[] command = new byte[] {0x00, (byte) 0x83, 0x00, 0x00, 0X00}; String commandHex = bytesToHex(command); byte[] outBufferXFRBlock = hexStringToByteArray("6F" + "05000000" + "00" + sequenceNumber + "00" + "0000" + commandHex); int outByteCount = connection.bulkTransfer(outEndpoint, outBufferXFRBlock, outBufferXFRBlock.length, TIMEOUT);
读取响应代码
final byte[] inBuffer = new byte[80]; int inByteCount = connection.bulkTransfer(inEndpoint, inBuffer, inBuffer.length, TIMEOUT);
可能的问题点及排查建议
1. XFRBlock封装格式是否合规
你拼接的XFRBlock头部6F是PC/SC协议中的XFR_BLOCK指令,但需要确认以下细节:
sequenceNumber格式:必须是两位十六进制字符串(对应1字节),如果你的sequenceNumber是整数类型,要确保转成两位十六进制(比如数字1要转成"01"而非"1"),否则会导致整个XFRBlock长度偏移,直接引发响应解析错误。- 长度字段
05000000:这是小端格式的APDU长度(5字节),看起来符合规范,但要确认你的读卡器是否要求大端格式,部分小众读卡器会对长度字节序有特殊要求。
2. 读取响应的缓冲区处理逻辑
- 不要直接使用完整的
inBuffer:bulkTransfer返回的inByteCount是实际读取的有效字节数,必须截取前inByteCount字节进行解析,缓冲区剩余字节可能是未覆盖的垃圾数据。 - 响应是带XFRBlock封装的:读卡器返回的不是原始APDU响应,需要先解析封装头部:
- 检查响应首字节是否为
6F(XFR_BLOCK响应标识) - 读取后续4字节并转换字节序,获取响应数据的实际长度
- 跳过序列号等头部字段,提取真正的APDU响应数据(包含SW状态字)
- 检查响应首字节是否为
3. 命令发送后的完整性验证
- 确认
outByteCount是否等于outBufferXFRBlock.length,如果发送字节数不足,说明命令未完整发送,必然导致响应异常。 - 部分高波特率读卡器需要发送后短暂等待再读取响应,可以尝试在发送命令后增加100-200ms的延迟(不要超过设置的TIMEOUT值)。
4. APDU命令的上下文合法性
0x00 0x83 0x00 0x00 0x00是GET RESPONSE命令,通常需要配合之前的命令使用(比如之前发送了需要后续获取响应的指令),如果单独发送该命令,读卡器可能返回错误响应,需要确认这个命令在当前读卡器状态下是否合法。
内容的提问来源于stack exchange,提问作者Tolkin
相关产品推荐
相关产品推荐

