如何取得Smart Card裝置 第二代金融卡的卡片序號 |
尚未結案
|
hank73317
一般會員 發表:20 回覆:47 積分:13 註冊:2008-12-12 發送簡訊給我 |
我看了一下前輩的作法,自己改依點~~~~寫的code~~
可以取得Smart Card裝置名稱了,步過沒法得到金融卡的序號(我用合作金庫的金融卡去try的,麻煩有寫過Smart Card的高手,幫我看一下吧~~~~謝謝 會部會有可能是SCardTransmit( ),這個API的下的參數步隊,~~~~~~ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace AAAA { public partial class Form1 : Form { public struct SCARD_IO_REQUEST { public int dwProtocol; public int cbPciLength; } public Form1() { InitializeComponent(); } [DllImport("WinScard.dll")] public static extern int SCardEstablishContext(int dwScope, int nNotUsed1, int nNotUsed2, ref int phContext); [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 SCardListReaderGroups(int hContext, ref string cGroups, ref int nStringSize); [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 SCardTransmit(int hCard,ref SCARD_IO_REQUEST pioSendPci, byte[] pbSendBuffer, int cbSendLength, ref SCARD_IO_REQUEST pioRecvPci, ref byte pbRecvBuffer, ref int pcbRecvLength); private void button1_Click(object sender, EventArgs e) { //First step in using smart cards is CSardEstablishContext() int nContext = 0; //system int nNotUsed1 = 0; int nNotUsed2 = 0; //handle to context for future calls to use int nRetVal1 = SCardEstablishContext(nContext, nNotUsed1, nNotUsed2, ref nContext); string mszReaders; string cReaderList = "" Convert.ToChar(0); int nReaderCount = -1; //used to split null delimited strings into string arrays char[] delimiter = new char[1]; textBox2.Text = delimiter[0].ToString(); //Second step in using smart cards is SCardListReaderGroups() to determin reader to use string cGroupList = "" ; int nStringSize = -1; //SCARD_AUTOALLOCATE int nRetVal2 = SCardListReaderGroups(nContext, ref cGroupList, ref nStringSize); if (nRetVal2 != 0) { DisplaySCError(nRetVal2, "SCardListReaderGroups()"); return; } string[] cGroups = cGroupList.Split(delimiter); /*foreach (string cName in cGroups) { MessageBox.Show("Reader Group: " cName); }*/ /*int nRetVal3 = SCardFreeMemory(this.nContext, ref cGroupList); if (nRetVal3 != 0) { DisplaySCError(nRetVal3,"SCardFreeMemory()"); return; }*/ int nRetVal4 = SCardListReaders(nContext, cGroups[0], ref cReaderList, ref nReaderCount); if (nRetVal4 != 0) { DisplaySCError(nRetVal4, "SCardListReaders()"); return; } textBox1.Text = cReaderList;//將smart Card 的裝置名稱秀出 //================================================= string[] cReaders = cReaderList.Split(delimiter); /*foreach (string cName in cReaders) { MessageBox.Show("Reader: " cName); }*/ /*int nRetVal5 = SCardFreeMemory(this.nContext, ref cReaderList); if (nRetVal5 != 0) { DisplaySCError(nRetVal5,"SCardFreeMemory()"); return; }*/ uint nShareMode = 1; //exclusive uint nPrefProtocol = 0x80000000; //default PTS int nCard = 0; int nActiveProtocol = 0; int nRetVal6 = SCardConnect(nContext, cReaders[0], nShareMode, nPrefProtocol, ref nCard, ref nActiveProtocol); if (nRetVal6 != 0) DisplaySCError(nRetVal6, "SCardConnect()"); //=================================== SCARD_IO_REQUEST SendPci, RecvPci; byte[] SelEFAPDU = { 0xA0, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00 }; //Select Elementary File 的 APDU byte[] ReadSNAPDU = { 0x00, 0xB0, 0x00, 0x04, 0x08 }; //由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; //下達 Select FE14 檔的 APDU SendPci.dwProtocol = RecvPci.dwProtocol = nActiveProtocol; SendPci.cbPciLength = RecvPci.cbPciLength = 8; if (SCardTransmit(nCard, ref SendPci, SelEFAPDU, SelEFAPDU.Length, ref RecvPci, ref SelEFRecvBytes[0], ref SelEFRecvLength) == 0) { if (SCardTransmit(nCard, ref SendPci, ReadSNAPDU, ReadSNAPDU.Length, ref RecvPci, ref SNRecvBytes[0], ref SnRecvLength) == 0) { Console.WriteLine("卡號為{0}", Encoding.Default.GetString(SNRecvBytes, 0, 16)); } } } //============================ private void DisplaySCError(int nErrCode, string cText) { string cErrString = ""; string ErrCode = String.Format("0x{0:X}", nErrCode); //例外的Error code處理 switch (ErrCode) { case "0x80100001": cErrString = "Internal Error"; break; case "0x80100002": cErrString = "Cancelled"; break; case "0x80100003": cErrString = "Invalid Handle"; break; case "0x80100004": cErrString = "Invalid Parameter"; break; case "0x80100005": cErrString = "Invalid Target"; break; case "0x80100006": cErrString = "No Memory"; break; case "0x80100007": cErrString = "Waited Too Long"; break; case "0x80100008": cErrString = "Insufficient Buffer"; break; case "0x80100009": cErrString = "Unknown Reader"; break; case "0x8010000A": cErrString = "Timeout"; break; case "0x8010000B": cErrString = "Sharing Violation"; break; case "0x8010000C": cErrString = "No Smart Card"; break; case "0x8010000D": cErrString = "Unknown Card"; break; case "0x8010000E": cErrString = "Can't Dispose"; break; case "0x8010000F": cErrString = "Proto Mismatch"; break; case "0x80100010": cErrString = "Not Ready"; break; case "0x80100011": cErrString = "Invalid Value"; break; case "0x80100012": cErrString = "System Cancelled"; break; case "0x80100013": cErrString = "Comm Error"; break; case "0x80100014": cErrString = "Unknown Error"; break; case "0x80100015": cErrString = "Invalid ATR"; break; case "0x80100016": cErrString = "Not Transacted"; break; case "0x80100017": cErrString = "Reader Unavailable"; break; case "0x80100018": cErrString = "Shutdown"; break; case "0x80100019": cErrString = "PCI Too Small"; break; case "0x8010001A": cErrString = "Reader Unsupported"; break; case "0x8010001B": cErrString = "Duplicate Reader"; break; case "0x8010001C": cErrString = "Card Unsupported"; break; case "0x8010001D": cErrString = "No Service"; break; case "0x8010001E": cErrString = "Service Stopped"; break; case "0x80100065": cErrString = "Unsupported Card"; break; case "0x80100066": cErrString = "Unresponsive Card"; break; case "0x80100067": cErrString = "Unpowered Card"; break; case "0x80100068": cErrString = "Reset Card"; break; case "0x80100069": cErrString = "Removed Card"; break; default: cErrString = "Unknown PC/SC Error Code - No Further Information Is Available"; break; } MessageBox.Show(String.Format("Error Code: 0x{0:X}\n\n" cErrString "\n\n" cText, nErrCode), "Smart Card PC/SC Error"); } } } 取得卡片序號的段code SCARD_IO_REQUEST SendPci, RecvPci; byte[] SelEFAPDU = { 0xA0, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00 }; //Select Elementary File 的 APDU byte[] ReadSNAPDU = { 0x00, 0xB0, 0x00, 0x04, 0x08 }; //由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; //下達 Select FE14 檔的 APDU SendPci.dwProtocol = RecvPci.dwProtocol = nActiveProtocol; SendPci.cbPciLength = RecvPci.cbPciLength = 8; if (SCardTransmit(nCard, ref SendPci, SelEFAPDU, SelEFAPDU.Length, ref RecvPci, ref SelEFRecvBytes[0], ref SelEFRecvLength) == 0) { if (SCardTransmit(nCard, ref SendPci, ReadSNAPDU, ReadSNAPDU.Length, ref RecvPci, ref SNRecvBytes[0], ref SnRecvLength) == 0) { Console.WriteLine("卡號為{0}", Encoding.Default.GetString(SNRecvBytes, 0, 16)); } } 會部會是有可能byte[] SelEFAPDU = { 0xA0, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00 }; //Select Elementary File 的 APDU byte[] ReadSNAPDU = { 0x00, 0xB0, 0x00, 0x04, 0x08 }; //由offset 0 讀取 0x10位 Binary 資料的 APDU 下錯了,步是第二代金融卡的APDU~~~~~~ |
hank73317
一般會員 發表:20 回覆:47 積分:13 註冊:2008-12-12 發送簡訊給我 |
|
hank73317
一般會員 發表:20 回覆:47 積分:13 註冊:2008-12-12 發送簡訊給我 |
各位大大,我的問題搞定了~~~~
Code給各位參考~~~~~ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace poi { public partial class Form1 : Form { public struct SCARD_IO_REQUEST { public int dwProtocol; public int cbPciLength; } //========================================================== public enum SCARD_STATE { // The application is unaware of the current state, and would like to know. The use // of this value results in an immediate return from state transition monitoring // services. This is represented by all bits set to zero. UNAWARE = 0x00000000, // The application requested that this reader be ignored. No other bits will be set. IGNORE = 0x00000001, // This implies that there is a difference between the state believed by the // application, and the state known by the Service Manager. When this bit is set, // the application may assume a significant state change has occurred on this reader. CHANGED = 0x00000002, // This implies that the given reader name is not recognized by the Service Manager. // If this bit is set, then CHANGED and IGNORE will also be set. UNKNOWN = 0x00000004, // This implies that the actual state of this reader is not available. If this bit // is set, then all the following bits are clear. UNAVAILABLE = 0x00000008, // This implies that there is not card in the reader. If this bit is set, all the // following bits will be clear. EMPTY = 0x00000010, // This implies that there is a card in the reader. PRESENT = 0x00000020, // This implies that there is a card in the reader with an ATR matching one of the // target cards. If this bit is set, PRESENT will also be set. This bit is only // returned on the SCardLocateCard() service. ATRMATCH = 0x00000040, // This implies that the card in the reader is allocated for exclusive use by // another application. If this bit is set, PRESENT will also be set. EXCLUSIVE = 0x00000080, // This implies that the card in the reader is in use by one or more other // applications, but may be connected to in shared mode. If this bit is set, // PRESENT will also be set. INUSE = 0x00000100, // This implies that the card in the reader is unresponsive or not supported by the // reader or software. MUTE = 0x00000200, // This implies that the card in the reader has not been powered up. UNPOWERED = 0x00000400 } public enum SCARD_SCOPE { // The context is a user context, and any database operations are performed within the // domain of the user. USER = 0x0000, // The context is that of the current terminal, and any database operations are performed // within the domain of that terminal. (The calling application must have appropriate // access permissions for any database actions.) TERMINAL = 0x0001, // The context is the system context, and any database operations are performed within the // domain of the system. (The calling application must have appropriate access permissions // for any database actions.) SYSTEM = 0x0002, GLOBAL = 0x0003 } public struct SCARD_READERSTATE { /// public string szReader; /// public IntPtr pvUserData; /// public SCARD_STATE dwCurrentState; /// public SCARD_STATE dwEventState; /// public UInt32 cbAtr; /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 33)] public byte[] rgbAtr; } public static string[] ListReaders() { int ReaderSize = -1; //SCARD_AUTOALLOCATE ErrorCode = SCardListReaders(ContextHandle, null, null, ref ReaderSize); byte[] ReaderBytes = new byte[ReaderSize]; ErrorCode = SCardListReaders(ContextHandle, null, ReaderBytes, ref ReaderSize); string[] ReaderList = Encoding.ASCII.GetString(ReaderBytes).Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries); return ReaderList; } private static void AppendOutput(string format, params object[] items) { Console.WriteLine(format, items); } private static void AppendOutput() { Console.WriteLine(); } public static string BytesToHex(byte[] ba, int length) { return BytesToHex(ba, 0, length); } public static byte[] MakeArray(byte[] by, int start, int length) { if (start < 0) start = 0; if (length < 0) length = 0; byte[] bb = new byte[length]; if (by != null) if (length > 0 && start < by.Length) Array.Copy(by, start, bb, 0, length); return bb; } public static string BytesToHex(byte[] ba, int start, int length) { byte[] tempb = MakeArray(ba, start, length); int len = 0; string separator = ""; string[] hexstrs = Array.ConvertAll { switch ( len) { case 16: separator = "\n"; len = 0; break; case 8: //separator = " "; break; case 4: case 12: separator = " "; break; default: separator = ""; break; } return b.ToString("X2") separator; }); return string.Join("", hexstrs).TrimEnd(separator.ToCharArray()); } //================================================================= public Form1() { InitializeComponent(); } [DllImport("winscard.dll")] public static extern int SCardGetStatusChange(int hContext, uint dwTimeout, ref SCARD_READERSTATE rgReaderStates, int cReaders); [DllImport("winscard.dll")] public static extern int SCardEstablishContext(SCARD_SCOPE dwScope, int nNotUsed1, int nNotUsed2, out int hContext); [DllImport("winscard.dll")] public static extern int SCardListReaders(int hContext, byte[] cGroups, byte[] cReaders, ref int nReaderCount); [DllImport("WinScard.dll")] public static extern int SCardListReaderGroups(int hContext, ref string cGroups, ref int nStringSize); [DllImport("WinScard.dll")] public static extern int SCardListReaders(int hContext, string cGroups, ref string cReaderLists, ref int nReaderCount); public static int ContextHandle = 0; public static int ErrorCode = 0; public static SCARD_READERSTATE[] readerState = null; public static string[] ReaderList = null; public static int nReaders = 1, iReader = -1; private void button1_Click(object sender, EventArgs e) { //建立 Smart Card API ErrorCode = SCardEstablishContext(SCARD_SCOPE.USER, 0, 0, out ContextHandle); //string[] CardList = ListCards(); //AppendOutput(string.Join("\n", CardList)); ReaderList = ListReaders(); nReaders = ReaderList.Length; readerState = new SCARD_READERSTATE[nReaders]; SCARD_STATE eventState = SCARD_STATE.UNAWARE; iReader = -1; String SmartCardATR=""; for (int i = 0; i < nReaders && iReader < 0; i ) { readerState[i].szReader = ReaderList[i]; readerState[i].dwCurrentState = SCARD_STATE.UNAWARE; ErrorCode = SCardGetStatusChange(ContextHandle, 250, ref readerState[i], 1); if (ErrorCode != 0) continue; eventState = readerState[i].dwEventState; readerState[i].dwCurrentState = eventState; SmartCardATR = SmartCardATR BytesToHex(readerState[i].rgbAtr, (int)readerState[i].cbAtr).ToString(); if (iReader < 0 && 0 != (SCARD_STATE.PRESENT & eventState)) iReader = i; } textBox1.Text = SmartCardATR; //============================================== char[] delimiter = new char[1]; //Second step in using smart cards is SCardListReaderGroups() to determin reader to use string cGroupList = ""; int nStringSize = -1; //SCARD_AUTOALLOCATE int nRetVal2 = SCardListReaderGroups(ContextHandle, ref cGroupList, ref nStringSize); if (nRetVal2 != 0) return; string[] cGroups = cGroupList.Split(delimiter); string cReaderList = "" Convert.ToChar(0); int nReaderCount = -1; /*foreach (string cName in cGroups) { MessageBox.Show("Reader Group: " cName); }*/ /*int nRetVal3 = SCardFreeMemory(this.nContext, ref cGroupList); if (nRetVal3 != 0) { DisplaySCError(nRetVal3,"SCardFreeMemory()"); return; }*/ int nRetVal4 = SCardListReaders(ContextHandle, cGroups[0], ref cReaderList, ref nReaderCount); if (nRetVal4 != 0) return; textBox2.Text = cReaderList; //=========================================== } } } |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |