2016-09-28 54 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

相關問題