using System;
using System.Text;
using System.Runtime.InteropServices;
class CitizenDigitalCertificateCardNoReader
{
public struct SCARD_IO_REQUEST
{
public int dwProtocol;
public int cbPciLength;
}
//引用 PC/SC(Personal Computer/Smart Card) API WinScard.dll
[DllImport("WinScard.dll")] public static extern int SCardEstablishContext(uint dwScope,
int nNotUsed1, int nNotUsed2, ref int phContext);
[DllImport("WinScard.dll")] public static extern int SCardReleaseContext(int phContext);
[DllImport("WinScard.dll")] public static extern int SCardConnect(int hContext, string cReaderName,
uint dwShareMode, uint dwPrefProtocol, ref int phCard, ref int ActiveProtocol);
[DllImport("WinScard.dll")] public static extern int SCardDisconnect(int hCard, int Disposition);
[DllImport("WinScard.dll")] public static extern int SCardListReaders(int hContext, string cGroups,
ref string cReaderLists, ref int nReaderCount);
[DllImport("WinScard.dll")] public static extern int SCardTransmit(int hCard,
ref SCARD_IO_REQUEST pioSendPci, byte[] pbSendBuffer, int cbSendLength,
ref SCARD_IO_REQUEST pioRecvPci, ref byte pbRecvBuffer, ref int pcbRecvLength);
static void Main(string[] args)
{
int ContextHandle = 0, CardHandle = 0, ActiveProtocol = 0, ReaderCount = -1;
string ReaderList = string.Empty; //讀卡機名稱列表
SCARD_IO_REQUEST SendPci, RecvPci;
byte[] SelEFAPDU = { 0x00, 0xA4, 0x02, 0x0C, 0x02, 0xFE, 0x14 }; //Select Elementary File 的 APDU
byte[] ReadSNAPDU = { 0x00, 0xB0, 0x00, 0x00, 0x10 }; //由offset 0 讀取 0x10位 Binary 資料的 APDU
byte[] SelEFRecvBytes = new byte[2]; //應回 90 00
int SelEFRecvLength = 2;
byte[] SNRecvBytes = new byte[18]; //接收卡號的 Byte Array
int SnRecvLength = 18;
//建立 Smart Card API
if (SCardEstablishContext(0, 0, 0, ref ContextHandle) == 0)
//列出可用的 Smart Card 讀卡機
if (SCardListReaders(ContextHandle, null, ref ReaderList, ref ReaderCount) == 0)
//建立 Smart Card 連線
if (SCardConnect(ContextHandle, ReaderList, 1, 2, ref CardHandle, ref ActiveProtocol) == 0)
{
SendPci.dwProtocol = RecvPci.dwProtocol = ActiveProtocol;
SendPci.cbPciLength = RecvPci.cbPciLength = 8;
//下達 Select FE14 檔的 APDU
if (SCardTransmit(CardHandle, ref SendPci, SelEFAPDU, SelEFAPDU.Length,
ref RecvPci, ref SelEFRecvBytes[0], ref SelEFRecvLength) == 0)
//下達讀取卡號指令
if (SCardTransmit(CardHandle, ref SendPci, ReadSNAPDU, ReadSNAPDU.Length,
ref RecvPci, ref SNRecvBytes[0], ref SnRecvLength) == 0)
Console.WriteLine("自然人憑證卡號為{0}",
Encoding.Default.GetString(SNRecvBytes, 0, 16));
}
Console.ReadKey();
}
}