通过 USB 连接的 APDU

Posted

技术标签:

【中文标题】通过 USB 连接的 APDU【英文标题】:APDU via USB Connection 【发布时间】:2015-06-17 07:59:26 【问题描述】:

我想创建一个 android 应用程序来查找我的 micro-usb(智能卡读卡器设备),所以我在接收智能卡中的数据时遇到问题(我通过方法 usbDeviceConnection.bulkTransfer 向智能卡发送了一个 0x 的 APDU... .但我不知道如何接收数据或回复的东西(它必须在我发送命令后回复卡中的数据给我)。当它回复时,我如何将十六进制编码或转换为字符串?

我猜,(参考代码)我有 2 个端点,所以我对端点输入和端点输出有疑问。这些参数是什么?如何使用它在设备和应用程序之间发送和接收数据?我觉得对还是不对? BroadcastReceiver 是做什么的?

protected void onCreate(Bundle savedInstanceState) 
   super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
   tv = (TextView) findViewById(R.id.textview);   
   //register the broadcast receiver
   mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
  IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
  registerReceiver(mUsbReceiver, filter);

  registerReceiver(mUsbDeviceReceiver, new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED));
  registerReceiver(mUsbDeviceReceiver, new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED));

  connectUsb();

这里是connectUSB方法。

private void connectUsb() 
  Toast.makeText(MainActivity.this,
   "connectUsb()",
  Toast.LENGTH_LONG).show();


  searchEndPoint();

   if (usbInterfaceFound != null) 
  setupUsbComm();

   threadUsbTx = new ThreadUsbTx(usbDeviceConnection, endpointOut);
   threadUsbTx.start();

   //bytes are APDU to send for get data from card.
   threadUsbTx.insertCmd(
   new byte[](byte) 0xA0, (byte) 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00);
   threadUsbTx.insertCmd(
   new byte[](byte)0x80, (byte)0xb0, 0x00, 0x04, 0x02, 0x00, 0x0d);
   threadUsbTx.insertCmd(
   new byte[]0x00, (byte)0xc0, 0x00, 0x00, 0x0d);
   
  

这里是类 ThreadUsbTx..

class ThreadUsbTx extends Thread 
   boolean running;

  UsbDeviceConnection txConnection;
  UsbEndpoint txEndpoint;
  Queue<byte[]> cmdQueue;
   byte[] cmdToSent;


  ThreadUsbTx(UsbDeviceConnection conn, UsbEndpoint endpoint) 
   txConnection = conn;
   txEndpoint = endpoint;
   cmdQueue = new LinkedList<byte[]>();
   cmdToSent = null;

   running = true;
  

   public void setRunning(boolean r) 
   running = r;
  

   public void insertCmd(byte[] cmd) 
   synchronized (cmdQueue) 
   cmdQueue.add(cmd);
  
  

   @Override
   public void run() 

   while (running) 

   synchronized (cmdQueue) 
   if (cmdQueue.size() > 0) 
   cmdToSent = cmdQueue.remove();
  
  

   if (cmdToSent != null) 

   final int usbResult = usbDeviceConnection.bulkTransfer(
   txEndpoint,
   cmdToSent,
   cmdToSent.length,
   0);

   final String s = new String(cmdToSent);
  String result = null;

   try 
  result = new String(cmdToSent,"TIS620"); // To Thai language
   catch (UnsupportedEncodingException e) 
  e.printStackTrace();
  

   final String finalResult = result;
  runOnUiThread(new Runnable() 

   @Override
   public void run() 
  Toast.makeText(MainActivity.this,
   finalResult+" "+String.format("%040x",cmdToSent),
  Toast.LENGTH_LONG).show();
  
  );
   cmdToSent = null;
   
  
  
  

【问题讨论】:

您的阅读器是否希望 APDU 直接通过 USB 连接传输,还是需要一些中间协议(例如,它是否像典型的智能卡阅读器那样遵循 CCID 设备类)? 我知道只有 APDU 可以与智能卡通信,所以我有一个示例应用程序,它可以通过 USB 连接发送 APDU。我反编译它,发现他们也使用USB连接。如果我必须知道任何事情,请给我更多建议。谢谢。 你的英文还行,注意不要在.?前面加空格,一直写“I”(绝不是“i”) vendorID = 1423 ProductID=38208 proname = EMV 智能卡读卡器再次感谢您。 :) 【参考方案1】:

与 USB 读卡器通信的最佳方式是使用符合 CCID 标准的读卡器和支持 OTG 的手机。看看Playstore中的App“CCID Reader Application Demo”。也有用the library 可用here。否则,您必须在代码中或多或少地实现 CCID 行为

【讨论】:

以上是关于通过 USB 连接的 APDU的主要内容,如果未能解决你的问题,请参考以下文章

Osmocom SIMtrace简介

在未连接智能卡的情况下发送带有 winscard.dll (PC/SC) 的 APDU

如何访问 Omnikey 3121 智能卡读卡器

如何通过 APDU 命令将 X509 证书存储在 SmartCard 中

通过 HID OMNIKEY 5427 CK 向卡发送 APDU 命令

从通过 USB 连接的外部天线获取数据