【发布时间】:2016-09-28 21:50:24
【问题描述】:
我正在尝试读取爱沙尼亚身份证的个人文件。
我需要将以下数据发送到卡(从 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 中的时间过长。事件顺序如下:
- 卡已连接到读卡器
- 程序从
SCardStatusChange返回并开始处理卡片 - 在尝试连接到卡(
SCardConnect或SCardReconnect)时,反复收到错误SCARD_E_SHARING_VIOLATION,持续大约 5 秒 - 然后,在尝试连接时,会在 3 到 30 秒之间的任何时间收到错误
SCARD_E_PROTO_MISMATCH,可能更长。 - 之后,卡连接成功并读取数据。
我能否以某种方式在 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!
}
}
【问题讨论】:
-
1) 对于进行连接,使用的协议不应在性能上产生显着差异。 2) 支持 T=0 和 T=1 的卡已经足够不寻常了 3) 如有疑问,请始终使用 T=1,这对于应用程序来说更容易,并且在安全消息传递方面更健壮。
标签: c++ winapi smartcard winscard id-card