我用:
我需要从智能卡中获取 ICCID,但是当我使用 Chilkat DLL 中的
TransmitHex()
时,我总是收到错误代码:
0x8010002f
首先我尝试了 Chilkat 的示例:https://www.example-code.com/delphiDll/pcsc_get_card_uid.asp
procedure TForm1.Button1Click(Sender: TObject);
var
scard: HCkSCard;
success: Boolean;
json: HCkJsonObject;
name: PWideChar;
state: PWideChar;
vendorName: PWideChar;
systemName: PWideChar;
cardAtr: PWideChar;
cardWindowsMiniDriver: PWideChar;
cardWindowsCryptoProvider: PWideChar;
cardWindowsKeyStorageProvider: PWideChar;
serialNumber: PWideChar;
i: Integer;
count_i: Integer;
bdRecv: HCkBinData;
numBytes: Integer;
begin
// This example requires the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
scard := CkSCard_Create();
// First establish a context to the PC/SC Resource Manager
success := CkSCard_EstablishContext(scard,'user');
if (success = False) then
begin
Memo1.Lines.Add(CkSCard__lastErrorText(scard));
Exit;
end;
// Use your own smart card reader name here.
success := CkSCard_Connect(scard, CkSCard__connectedReader(scard),'shared','no_preference');
if (success = False) then
begin
Memo1.Lines.Add(CkSCard__lastErrorText(scard));
Exit;
end;
Memo1.Lines.Add('Connected reader: ' + CkSCard__connectedReader(scard));
Memo1.Lines.Add('Active protocol: ' + CkSCard__activeProtocol(scard));
Memo1.Lines.Add('ATR: ' + CkSCard__cardAtr(scard));
Memo1.Lines.Add('Reader Status: ' + CkSCard__readerStatus(scard));
// Send the APDU command 0xFF, 0xCA, 0x00, 0x00, 0x00
bdRecv := CkBinData_Create();
success := CkSCard_TransmitHex(scard,CkSCard__activeProtocol(scard),'FFCA000000',bdRecv,32);
if (success = True) then
begin
Memo1.Lines.Add('Received: ' + CkBinData__getEncoded(bdRecv,'hex'));
// The UID is the returned data without the final 2 bytes.
numBytes := CkBinData_getNumBytes(bdRecv);
if (numBytes > 2) then
begin
Memo1.Lines.Add('UID: ' + CkBinData__getEncodedChunk(bdRecv,0,numBytes - 2,'hex'));
end;
end
else
begin
Memo1.Lines.Add(CkSCard__lastErrorText(scard));
end;
// Disconnect from this reader.
success := CkSCard_Disconnect(scard,'leave');
if (success = False) then
begin
Memo1.Lines.Add(CkSCard__lastErrorText(scard));
end;
// Applications should always release the context when finished.
success := CkSCard_ReleaseContext(scard);
if (success = False) then
begin
Memo1.Lines.Add(CkSCard__lastErrorText(scard));
end;
CkSCard_Dispose(scard);
CkBinData_Dispose(bdRecv);
end;
我得到的是:
UnlockBundle: Oh yeah Test Test1 Test2 0: Gemalto USB SmartCard Reader 0 Connected reader: Gemalto USB SmartCard Reader 0 Test3 Test4 Connected reader: Gemalto USB SmartCard Reader 0 Active protocol: T0 ATR: 3B9F96801FC68031E073FE211B66D00221AB11180180 Reader Status: specific ChilkatLog: TransmitHex(1844ms): DllDate: Jun 29 2024 ChilkatVersion: 9.5.0.99 UnlockStatus: 1 Architecture: Little Endian; 32-bit Language: Delphi DLL VerboseLogging: 1 transmit(1844ms): PcscErrorCode: 0x8010002f SCardTransmit failed. --transmit Failed. --TransmitHex --ChilkatLog Test5 Test6 Test7
后来我发现需要PIN的智能卡没有UID。但我猜这会导致不同的错误。
我还尝试了一些方法来获取我需要的 ICCID:
procedure TForm1.Button1Click(Sender: TObject);
var
scard: HCkSCard;
success: Boolean;
json: HCkJsonObject;
name: PWideChar;
state: PWideChar;
vendorName: PWideChar;
systemName: PWideChar;
cardAtr: PWideChar;
cardWindowsMiniDriver: PWideChar;
cardWindowsCryptoProvider: PWideChar;
cardWindowsKeyStorageProvider: PWideChar;
serialNumber: PWideChar;
i: Integer;
count_i: Integer;
bdRecv: HCkBinData;
numBytes: Integer;
begin
// This example requires the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
scard := CkSCard_Create();
// First establish a context to the PC/SC Resource Manager
success := CkSCard_EstablishContext(scard,'user');
if (success = False) then
begin
Memo1.Lines.Add(CkSCard__lastErrorText(scard));
Exit;
end;
// Use your own smart card reader name here.
success := CkSCard_Connect(scard, CkSCard__connectedReader(scard),'shared','no_preference');
if (success = False) then
begin
Memo1.Lines.Add(CkSCard__lastErrorText(scard));
Exit;
end;
Memo1.Lines.Add('Connected reader: ' + CkSCard__connectedReader(scard));
Memo1.Lines.Add('Active protocol: ' + CkSCard__activeProtocol(scard));
Memo1.Lines.Add('ATR: ' + CkSCard__cardAtr(scard));
Memo1.Lines.Add('Reader Status: ' + CkSCard__readerStatus(scard));
//Get ICCID
// Send the APDU command 0xA0, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00
bdRecv := CkBinData_Create();
success := CkSCard_TransmitHex(scard,CkSCard__activeProtocol(scard),'A0A40000023F00',bdRecv,32);
if (success = True) then
begin
Memo1.Lines.Add('Received: ' + CkBinData__getEncoded(bdRecv,'hex'));
// Select MF
numBytes := CkBinData_getNumBytes(bdRecv);
if (numBytes > 2) then
begin
Memo1.Lines.Add('Select MF: ' + CkBinData__getEncodedChunk(bdRecv,0,numBytes - 2,'hex'));
end;
end
else
begin
Memo1.Lines.Add(CkSCard__lastErrorText(scard));
end;
// Send the APDU command 0xA0, 0xA4, 0x00, 0x00, 0x02, 0x2F, 0xE2
bdRecv := CkBinData_Create();
success := CkSCard_TransmitHex(scard,CkSCard__activeProtocol(scard),'A0A40000022FE2',bdRecv,32);
if (success = True) then
begin
Memo1.Lines.Add('Received: ' + CkBinData__getEncoded(bdRecv,'hex'));
// Select ICCID
numBytes := CkBinData_getNumBytes(bdRecv);
if (numBytes > 2) then
begin
Memo1.Lines.Add('Select ICCID: ' + CkBinData__getEncodedChunk(bdRecv,0,numBytes - 2,'hex'));
end;
end
else
begin
Memo1.Lines.Add(CkSCard__lastErrorText(scard));
end;
// Send the APDU command 0xA0, 0xB0, 0x00, 0x00, 0x0A
bdRecv := CkBinData_Create();
success := CkSCard_TransmitHex(scard,CkSCard__activeProtocol(scard),'A0B000000A',bdRecv,32);
if (success = True) then
begin
Memo1.Lines.Add('Received: ' + CkBinData__getEncoded(bdRecv,'hex'));
// Read the 10 bytes of ICCID EF
numBytes := CkBinData_getNumBytes(bdRecv);
if (numBytes > 2) then
begin
Memo1.Lines.Add('Read ICCID: ' + CkBinData__getEncodedChunk(bdRecv,0,numBytes - 2,'hex'));
end;
end
else
begin
Memo1.Lines.Add(CkSCard__lastErrorText(scard));
end;
//END
// Disconnect from this reader.
success := CkSCard_Disconnect(scard,'leave');
if (success = False) then
begin
Memo1.Lines.Add(CkSCard__lastErrorText(scard));
end;
// Applications should always release the context when finished.
success := CkSCard_ReleaseContext(scard);
if (success = False) then
begin
Memo1.Lines.Add(CkSCard__lastErrorText(scard));
end;
CkSCard_Dispose(scard);
CkBinData_Dispose(bdRecv);
end;
但是错误结果还是一样。
一些备注:
我假设您将 ICCID 理解为卡的唯一序列号。这些差异很大(对于给定的智能卡,您甚至可能根本无法获取它),并且获取它的方式也因卡而异。
第一个示例中的代码显然尝试的是发送特殊的 APDU(“FFCA..”)并期望 ICCID 作为响应。这是一个读者特定命令,可能是错误的。
第二个示例中的代码使用 CLA 字节
A0
,这对于您的卡来说可能是正确的,但您似乎没有提供提示,您实际上正在寻址哪张卡,因为 Gemalto IDBridge K30 是一个读卡器。