2016-09-28 51 views
0

我正在尝试阅读爱沙尼亚身份证的个人文件。WinSCard SCARD_E_PROTO_MISMATCH连接到爱沙尼亚身份证时

我需要把下面的数据(从 here)发送到卡,以读取个人文件记录(即身份证号码,姓名等):

00 A4 00 0C   # We choose root folder 
00 A4 01 0C 02 EE EE # We choose folder EEEE 
00 A4 02 04 02 50 44 # We choose file 5044, which contains personal data 
00 B2 XX 04   # We read record XX (see table) from the personal data file 
        # The card responds 61 YY, where YY denotes the number of bytes waiting to be read 
00 C0 00 00 YY  # We read YY bytes from the card 
        # Card responds ... 90 00, where ... is the requested data and 90 00 means status OK 

然而,原始字节在T = 0协议中,并且卡在接受T = 0之前不合理地长时间卡在T = 1中。事件的顺序如下:

  1. 卡连接到读卡器
  2. 程序返回从SCardStatusChange并开始处理卡
  3. 在尝试连接到存储卡(SCardConnectSCardReconnect)收到SCARD_E_SHARING_VIOLATION错误一遍又一遍,大约5秒
  4. 然后,在尝试连接时,错误SCARD_E_PROTO_MISMATCH接收到3到30秒之间的任何地方,也许更多。
  5. 之后,卡成功连接并读取数据。

我可以在T = 0协议中以某种方式更快地连接到它吗?

的我的源代码的简化版本如下:

// NOTE: this is approximately what I do. 
// I haven't tested this code yet - it's almost 1 AM here. 
#include <winscard.h> 
void readSmartCard() { 
    LONG sCardErrorCode; 
    SCARDCONTEXT sCardContext; 
    DWORD sCardReaderStrLen = 1024; 
    wchar_t sCardReaderStr[1024]; 
    SCARDHANDLE sCardHandle; 
    DWORD sCardActiveProtocol; 
    SCARD_READERSTATE readerState; 

    sCardErrorCode = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &sCardContext); 

    // error handling macro 

    ZeroMemory(&sCardReaderState, sizeof(sCardReaderState)); 
    sCardReaderState.szReader = L"\\\\?PnP?\\Notification"; 
    sCardReaderState.pvUserData = nullptr; 
    sCardReaderState.dwEventState = SCARD_STATE_PRESENT; 

    sCardErrorCode = SCardGetStatusChange(sCardContext, INFINITE, &readerState, 1); 

    // e.h.m 

    if (readerState.dwCurrentState == 65538) { 
     sCardErrorCode = SCardListReaders(sCardContext, NULL, sCardReaderStr, &sCardReaderStrLen); 
     // e.h.m 
     readerState.szReader = sCardReaderStr; 
    } 

    sCardErrorCode = SCardGetStatusChange(sCardContext, INFINITE, &readerState, 1); 
    // e.h.m 

    if (sCardReaderState.dwEventState & SCARD_STATE_PRESENT) { 

     while (true) { 
      sCardErrorCode = SCardConnect(sCardContext, readerState.szReader, SCARD_SHARE_EXCLUSIVE, 
       SCARD_PROTOCOL_T0, &sCardHandle, &sCardActiveProtocol); 

      // e.h.m 
      printf("%x", sCardErrorCode); 
      // this will print: 
      // 8010000b (for around 5s) 
      // 8010000f (for around 20s) 
      if (sCardErrorCode == SCARD_S_SUCCESS) { 
       break; 
      } 
      Sleep(1000); 
     } 

     // open personal file and read data, yay! 
    } 
} 
+0

1)做一个连接所使用的协议不应该使在性能上noticable差。 2)支持T = 0以及T = 1的卡足够不寻常3)如果有疑问,总是使用T = 1,它在应用程序中更容易并且在安全消息传递方面更加健壮。 – guidot

回答

0

经过漫长的互联网冲浪之后,我发现没有必要更改命令。

我简单地需要一个额外的零字节添加到发送读/开放命令的结束,和接收数据作为读取命令的响应,而不是使用单独的命令来接收的字节,以及。 (T = 0使用一个“请求数据/读取数据”模式,而T = 1刚好与数据来响应,好像)

我还需要改变所有提及的SCARD_PCI_T0有条件使用SCARD_PCI_T1并使SCardConnect()功能也接受T1。

我会在这里发布后一个体面的代码示例。

0

你问SCardConnect()为只对T0协议独占访​​问,因此,如果卡在使用中,则返回SCARD_E_SHARING_VIOLATION,如果该卡未使用,但T1处于活动状态,则将返回SCARD_E_PROTO_MISMATCH

SCardGetStatusChange()报告通知时,您只会检查SCARD_STATE_PRESENT标志,但也可以存在其他标志,例如SCARD_STATE_INUSE

如果您需要独家访问阅读器,则必须等到SCARD_STATE_INUSE被清除,并且/或SCARD_E_SHARING_VIOLATION不再开始报告。除此之外,您无法做任何事情,除非您更改逻辑以允许以共享模式而不是独占模式进行连接。

如果你想连接到读卡器,无论其当前的协议(从而获得独占访问更快),你可以问SCardConnect()接受T0T1协议的同时,中用OR在一起在dwPreferredProtocol参数中(请参阅documentation中的示例)。然后,如果pdwActiveProtocol参数输出T1是活动协议,则可以在读取卡之前等待状态更改为T0协议。

+0

谢谢你的回复。我会改善卡已经被占用的情况。但是,我不知道如何在T = 1中执行我需要的操作(导航到文件夹,打开个人数据文件,读取记录),这阻止了我支持该协议。如果我无法在T = 0中更快地打开卡片,我会研究T = 1,看看我是否也可以在那里做我所需要的。 (在这种情况下,独占访问也可能毫无用处,但我试图达到最终期限,因此我想避免与共享有关的任何问题) – boxmein

相关问题