c++ - 连接到爱沙尼亚身份证时的 WinSCard SCARD_E_PROTO_MISMATCH

标签 c++ winapi smartcard winscard id-card

我正在尝试阅读爱沙尼亚身份证的个人文件。

我需要将以下数据发送到卡(从
here ) 以从个人文件中读取记录(即 ID 号、姓名等):

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 协议(protocol)中,并且卡在接受 T=0 之前卡在 T=1 的时间过长。事件顺序如下:
  • 卡附在读卡器上
  • 程序从 SCardStatusChange 返回并开始处理卡片
  • 在尝试连接到卡( SCardConnectSCardReconnect )时出现错误 SCARD_E_SHARING_VIOLATION一遍又一遍地收到,大约 5 秒
  • 然后,在尝试连接时,错误 SCARD_E_PROTO_MISMATCH接收时间在 3 到 30 秒之间,甚至更多。
  • 之后,卡连接成功并读取数据。

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

    我的源代码的简化版本如下:
    // 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!
        }
    }
    

    最佳答案

    在互联网上搜索了很长时间后,我发现不需要更改命令。

    我只需要在传输的读取/打开命令的末尾添加一个额外的零字节,并接收数据作为读取命令的响应,而不是使用单独的命令来接收字节。 (T=0 使用“请求数据/读取数据”模型,而 T=1 似乎只是响应数据)

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

    我稍后会在这里发布一个不错的代码示例。

    关于c++ - 连接到爱沙尼亚身份证时的 WinSCard SCARD_E_PROTO_MISMATCH,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39758253/

    相关文章:

    java - 将 Web 应用程序与 DSC 卡集成

    windows - Windows 中的智能卡登录是否绑定(bind)到微型驱动程序和 MS 基本 CSP 或任何 CSP 都可以工作?

    c++ - object *operator<<(object* one, type& two);

    C++ 模板特化问题

    c++ - 按位读取文件 C++

    winapi - Windows上本地IPC的套接字与命名管道?

    c++ - 使用自定义字符串参数捕获抛出异常

    c++ - 创建具有固定顶部坐标的可调整大小的窗口

    C#:解码 OAEP 填充奇怪问题时出错

    C++ : double iteration through map