<strike id="tpvd9"><dfn id="tpvd9"></dfn></strike>

        <em id="tpvd9"></em>

          <address id="tpvd9"></address>
            <dfn id="tpvd9"><sub id="tpvd9"></sub></dfn>

            <thead id="tpvd9"><noframes id="tpvd9">
            <ruby id="tpvd9"></ruby>

                  <thead id="tpvd9"></thead>
                  歡迎您訪(fǎng)問(wèn)鄭州興邦電子股份有限公司官方網(wǎng)站!
                  阿里巴巴誠信通企業(yè)
                  全國咨詢(xún)熱線(xiàn):40000-63966
                  興邦電子,中國水控機第一品牌

                  聯(lián)系興邦電子

                  全國咨詢(xún)熱線(xiàn):40000-63966

                  售后:0371-55132951/55132952

                  工廠(chǎng):河南省 鄭州市 高新區蓮花街電子電器產(chǎn)業(yè)園

                  VC中PC/SC智能卡接口的編程

                  文章出處:http://psychicreadingswithdeb.com 作者:蔣遂平&nbsp;&nbsp; 人氣: 發(fā)表時(shí)間:2011年10月09日

                  [文章內容簡(jiǎn)介]:終端應用程序需要通過(guò)讀卡器來(lái)訪(fǎng)問(wèn)智能卡,在一個(gè)系統中,通常存在多家廠(chǎng)商提供的讀卡器,因此需要一個(gè)統一的讀卡器設備驅動(dòng)接口。

                       1 引言

                      完整的智能卡應用系統由后臺服務(wù)程序、主機或終端應用程序和智能卡等組成,其中,后臺服務(wù)程序提供了支持智能卡的服務(wù)。例如,在一個(gè)電子付款系統中,后臺服務(wù)程序可以提供到信用卡和帳戶(hù)信息的訪(fǎng)問(wèn);主機或終端應用程序一般存在于臺式機或者終端、電子付款終端、手機或者一個(gè)安全子系統中,終端應用程序要處理用戶(hù)、智能卡和后臺服務(wù)程序之間的通訊;智能卡則存儲用戶(hù)的一些信息。 

                      終端應用程序需要通過(guò)讀卡器來(lái)訪(fǎng)問(wèn)智能卡,在一個(gè)系統中,通常存在多家廠(chǎng)商提供的讀卡器,因此需要一個(gè)統一的讀卡器設備驅動(dòng)接口。 

                      隨著(zhù)智能卡的廣泛應用,為解決計算機與各種讀卡器之間的互操作性問(wèn)題,人們提出了PC/SC(Personal Computer/Smart Card)規范,PC/SC規范作為讀卡器和卡與計算機之間有一個(gè)標準接口,實(shí)現不同生產(chǎn)商的卡和讀卡器之間的互操作性,其獨立于設備的 API使得應用程序開(kāi)發(fā)人員不必考慮當前實(shí)現形式和將來(lái)實(shí)現形式之間的差異,并避免了由于基本硬件改變而引起的應用程序變更,從而降低了軟件開(kāi)發(fā)成本。

                      Microsoft在其Platform SDK中實(shí)現了PC/SC,作為連接智能卡讀卡器與計算機的一個(gè)標準模型,提供了獨立于設備的 API,并與Windows平臺集成。因此,我們可以用PC/SC接口來(lái)訪(fǎng)問(wèn)智能卡。

                      2 PC/SC概述

                      PC/SC接口包含30多個(gè)以Scard為前綴的函數,所有函數的原型都在winscard.h中聲明,應用程序需要包含winscard.lib,所有函數的正常返回值都是SCARD_S_SUCCESS。在這30多個(gè)函數中,常用的函數只有幾個(gè),與智能卡的訪(fǎng)問(wèn)流程(圖2)對應,下面將詳細介紹這些常用函數。

                      3 PC/SC的使用

                      3.1建立資源管理器的上下文

                      函數ScardEstablishContext()用于建立將在其中進(jìn)行設備數據庫操作的資源管理器上下文(范圍)。 

                      函數原型:LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext);
                  各個(gè)參數的含義:(1)dwScope:輸入類(lèi)型;表示資源管理器上下文范圍,取值為:SCARD_SCOPE_USER(在用戶(hù)域中完成設備數據庫操作)、SCARD_SCOPE_SYSTEM(在系統域中完成設備數據庫操作)。要求應用程序具有相應的操作權限。(2)pvReserved1:輸入類(lèi)型;保留,必須為NULL。(3)pvReserved2:輸入類(lèi)型;保留,必須為NULL。(4)phContext:輸出類(lèi)型;建立的資源管理器上下文的句柄。 

                      下面是建立資源管理器上下文的代碼:

                      SCARDCONTEXT hSC; 
                      LONG lReturn; 
                      lReturn = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &hSC); 
                      if ( lReturn!=SCARD_S_SUCCESS ) 
                      printf("Failed SCardEstablishContext\n");

                      3.2 獲得系統中安裝的讀卡器列表

                      函數ScardListReaders()可以列出系統中安裝的讀卡器的名字。 

                      函數原型:LONG SCardListReaders(SCARDCONTEXT hContext, LPCTSTR mszGroups, LPTSTR mszReaders, LPDWORD pcchReaders);
                  各個(gè)參數的含義:(1)hContext:輸入類(lèi)型;ScardEstablishContext()建立的資源管理器上下文的句柄,不能為NULL。(2)mszGroups:輸入類(lèi)型;讀卡器組名,為NULL時(shí),表示列出所有讀卡器。(3)mszReaders:輸出類(lèi)型;系統中安裝的讀卡器的名字,各個(gè)名字之間用’\0’分隔,最后一個(gè)名字后面為兩個(gè)連續的’\0’。(4)pcchReaders:輸入輸出類(lèi)型;mszReaders的長(cháng)度。

                      系統中可能安裝多個(gè)讀卡器,因此,需要保存各個(gè)讀卡器的名字,以便以后與需要的讀卡器建立連接。

                      下面是獲得系統中安裝的讀卡器列表的代碼:

                      char mszReaders[1024];
                      LPTSTR pReader, pReaderName[2]; 
                      DWORD dwLen=sizeof(mzsReaders); 
                      int nReaders=0; 
                      lReturn = SCardListReaders(hSC, NULL, (LPTSTR)mszReaders, &dwLen); 
                      if ( lReturn==SCARD_S_SUCCESS ) 
                      { 
                      pReader = (LPTSTR)pmszReaders; 
                      while (*pReader !='\0' ) 
                      { 
                      if ( nReaders<2 ) //使用系統中前2個(gè)讀卡器 
                      pReaderName[nReaders++]=pReader; 
                      printf("Reader: %S\n", pReader ); 
                      //下一個(gè)讀卡器名 
                      pReader = pReader + strlen(pReader) + 1; 
                      } 
                      }

                      3.3 與讀卡器(智能卡)連接 

                      函數ScardConnect()在應用程序與讀卡器上的智能卡之間建立一個(gè)連接。

                       函數原型:LONG SCardConnect(SCARDCONTEXT hContext, LPCTSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol);

                      各個(gè)參數的含義:(1)hContext:輸入類(lèi)型;ScardEstablishContext()建立的資源管理器上下文的句柄。(2)szReader:輸入類(lèi)型;包含智能卡的讀卡器名稱(chēng)(讀卡器名稱(chēng)由ScardListReaders()給出)。(3)dwShareMode:輸入類(lèi)型;應用程序對智能卡的操作方式,SCARD_SHARE_SHARED(多個(gè)應用共享同一個(gè)智能卡)、SCARD_SHARE_EXCLUSIVE(應用獨占智能卡)、SCARD_SHARE_DIRECT(應用將智能卡作為私有用途,直接操縱智能卡,不允許其它應用訪(fǎng)問(wèn)智能卡)。(4)dwPreferredProtocols:輸入類(lèi)型;連接使用的協(xié)議,SCARD_PROTOCOL_T0(使用T=0協(xié)議)、SCARD_PROTOCOL_T1(使用T=1協(xié)議)。(5)phCard:輸出類(lèi)型;與智能卡連接的句柄。(6)PdwActiveProtocol:輸出類(lèi)型;實(shí)際使用的協(xié)議。

                      下面是與智能卡建立連接的代碼:

                      SCARDHANDLE hCardHandle[2]; 
                      DWORD dwAP; 
                      lReturn = SCardConnect( hContext, pReaderName[0], SCARD_SHARE_SHARED, 
                      SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCardHandle[0], &dwAP ); 
                      if ( lReturn!=SCARD_S_SUCCESS ) 
                      { 
                      printf("Failed SCardConnect\n"); 
                      exit(1); 
                      }

                      與智能卡建立連接后,就可以向智能卡發(fā)送指令,與其交換數據了。

                      3.4 向智能卡發(fā)送指令

                      函數ScardTransmit()向智能卡發(fā)送指令,并接受返回的數據。

                      函數原型:LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_I0_REQUEST pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength, LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength);

                      各個(gè)參數的含義:(1)hCard:輸入類(lèi)型;與智能卡連接的句柄。(2)pioSendPci:輸入類(lèi)型;指令的協(xié)議頭結構的指針,由SCARD_IO_REQUEST結構定義。后面是使用的協(xié)議的協(xié)議控制信息。一般使用系統定義的結構,SCARD_PCI_T0(T=0協(xié)議)、 SCARD_PCI_T1(T=1協(xié)議)、SCARD_PCI_RAW(原始協(xié)議)。(3)pbSendBuffer:輸入類(lèi)型;要發(fā)送到智能卡的數據的指針。(4)cbSendLength:輸入類(lèi)型;pbSendBuffer的字節數目。(5)pioRecvPci:輸入輸出類(lèi)型;指令協(xié)議頭結構的指針,后面是使用的協(xié)議的協(xié)議控制信息,如果不返回協(xié)議控制信息,可以為NULL。(6)pbRecvBuffer:輸入輸出類(lèi)型;從智能卡返回的數據的指針。(7)pcbRecvLength:輸入輸出類(lèi)型;pbRecvBuffer的大小和實(shí)際大小。

                      對于T=0協(xié)議,收發(fā)緩沖的用法如下: 

                      (a)向智能卡發(fā)送數據:要向智能卡發(fā)送n>0字節數據時(shí),pbSendBuffer 前4字節分別為T(mén)=0的CLA、INS、P1、P2,第5字節是n,隨后是n字節的數據;cbSendLength值為n+5(4字節頭+1字節Lc+n字節數據)。PbRecvBuffer將接收SW1、SW2狀態(tài)碼;pcbRecvLength值在調用時(shí)至少為2,返回后為2。 

                      BYTE recvBuffer[260]; 
                      int sendSize, recvSize; 
                      BTYE sw1, sw2; 
                      BYTE select_mf[]={0xC0, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00}; 
                      sendSize=7; 
                      recvSize=sizeof(recvBuffer); 
                      lReturn = SCardTransmit(hCardHandle[0], SCARD_PCI_T0, select_mf, sendSize, 
                      NULL, recvBuffer, &recvSize); 
                      if ( lReturn != SCARD_S_SUCCESS ) 
                      { 
                      printf("Failed SCardTransmit\n"); 
                      exit(1); 
                      } 
                      //返回的數據,recvSize=2 
                      sw1=recvBuffer[recvSize-2]; 
                      sw2=recvBuffer[recvSize-1];

                      (b)從智能卡接收數據:為從智能卡接收n>0字節數據,pbSendBuffer 前4字節分別為T(mén)=0的CLA、INS、P1、P2,第5字節是n(即Le),如果從智能卡接收256字節,則第5字節為0;cbSendLength值為5(4字節頭+1字節Le)。PbRecvBuffer將接收智能卡返回的n字節,隨后是SW1、SW2狀態(tài)碼;pcbRecvLength的值在調用時(shí)至少為 n+2,返回后為n+2。

                   

                      BYTE get_challenge[]={0x00, 0x84, 0x00, 0x00, 0x08}; 
                      sendSize=5; 
                      recvSize=sizeof(recvBuffer); 
                      lReturn = SCardTransmit(hCardHandle[0], SCARD_PCI_T0, get_challenge, 
                      sendSize, NULL, recvBuffer, &recvSize); 
                      if ( lReturn != SCARD_S_SUCCESS ) 
                      { 
                      printf("Failed SCardTransmit\n"); 
                      exit(1); 
                      } 
                      //返回的數據, recvSize=10 
                      sw1=recvBuffer[recvSize-2]; 
                      sw2=recvBuffer[recvSize-1]; 
                      //data=recvBuffer[0]----recvBuffer[7]

                      (c)向智能卡發(fā)送沒(méi)有數據交換的命令:應用程序既不向智能卡發(fā)送數據,也不從智能卡接收數據,pbSendBuffer 前4字節分別為T(mén)=0的CLA、INS、P1、P2,不發(fā)送P3;cbSendLength 值必須為4。PbRecvBuffer從智能卡接收SW1、SW2狀態(tài)碼;pcbRecvLength值在調用時(shí)至少為2,返回后為2。

                      BYTE set_flag[]={0x80, 0xFE, 0x00, 0x00}; 
                      sendSize=4; 
                      recvSize=sizeof(recvBuffer); 
                      lReturn = SCardTransmit(hCardHandle[0], SCARD_PCI_T0, set_flag, sendSize, 
                      NULL, recvBuffer, &recvSize); 
                      if ( lReturn != SCARD_S_SUCCESS ) 
                      { 
                      printf("Failed SCardTransmit\n"); 
                      exit(1); 
                      } 
                      //返回的數據,recvSize=2 
                      sw1=recvBuffer[recvSize-2]; 
                      sw2=recvBuffer[recvSize-1];

                      (d)向智能卡發(fā)送具有雙向數據交換的命令:T=0協(xié)議中,應用程序不能同時(shí)向智能卡發(fā)送數據,并從智能卡接收數據,即發(fā)送到智能卡的指令中,不能同時(shí)有Lc和Le。這只能分兩步實(shí)現:向智能卡發(fā)送數據,接收智能卡返回的狀態(tài)碼,其中,SW2是智能卡將要返回的數據字節數目;從智能卡接收數據(指令為0x00、0xC0、0x00、0x00、Le)。

                      BYTE get_response={0x00, 0xc0, 0x00, 0x00, 0x00}; 
                      BYTE internal_auth[]={0x00, 0x88, 0x00, 0x00, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; 
                      sendSize=13; 
                      recvSize=sizeof(recvBuffer); 
                      lReturn = SCardTransmit(hCardHandle[0], SCARD_PCI_T0, internal_auth, 
                      sendSize, NULL, recvBuffer, &recvSize); 
                      if ( lReturn != SCARD_S_SUCCESS ) 
                      { 
                      printf("Failed SCardTransmit\n"); 
                      exit(1); 
                      } 
                      //返回的數據,recvSize=2 
                      sw1=recvBuffer[recvSize-2]; 
                      sw2=recvBuffer[recvSize-1]; 
                      if ( sw1!=0x61 ) 
                      { 
                      printf("Failed Command\n"); 
                      exit(1); 
                      } 
                      get_response[4]=sw2; 
                      sendSize=5; 
                      recvSize=sizeof(recvBuffer); 
                      lReturn = SCardTransmit(hCardHandle[0], SCARD_PCI_T0, get_response, 
                      sendSize, NULL, recvBuffer, &recvSize); 
                      if ( lReturn != SCARD_S_SUCCESS ) 
                      { 
                      printf("Failed SCardTransmit\n"); 
                      exit(1); 
                      } 
                      //返回的數據,recvSize=10 
                      sw1=recvBuffer[recvSize-2]; 
                      sw2=recvBuffer[recvSize-1]; 
                      //data=recvBuffer[0]----recvBuffer[7]

                      3.5 斷開(kāi)與讀卡器(智能卡)的連接

                      在與智能卡的數據交換完成后,可以使用函數ScardDisconnect()終止應用與智能卡之間的連接。 

                      函數原型:LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition); 
                      各個(gè)參數的含義:(1)hCard:輸入類(lèi)型;與智能卡連接的句柄。(2)dwDisposition:輸入類(lèi)型;斷開(kāi)連接時(shí),對智能卡的操作,SCARD_LEAVE_CARD(不做任何操作)、SCARD_RESET_CARD(復位智能卡)、SCARD_UNPOWER_CARD(給智能卡掉電)、SCARD_EJECT_CARD(彈出智能卡)。 

                      下面是斷開(kāi)與智能卡連接的代碼:

                      lReturn = SCardDisconnect(hCardHandle[0], SCARD_LEAVE_CARD); 
                      if ( lReturn != SCARD_S_SUCCESS ) 
                      { 
                      printf("Failed SCardDisconnect\n"); 
                      exit(1); 
                      }

                      3.6 釋放資源管理上下文

                      在應用程序終止前時(shí),應該調用函數ScardReleaseContext()釋放資源管理器的上下文。 
                      函數原型:LONG SCardReleaseContext(SCARDCONTEXT hContext); 
                      各個(gè)參數含義:(1)hContext:輸入類(lèi)型;ScardEstablishContext()建立的資源管理器上下文的句柄,不能為NULL。 
                      下面是釋放資源管理上下文的代碼: 
                      lReturn = SCardReleaseContext(hSC); 
                      if ( lReturn!=SCARD_S_SUCCESS ) 
                      printf("Failed SCardReleaseContext\n");

                      4 小結

                      以上介紹的通過(guò)PC/SC來(lái)操作智能卡的流程,可以封裝在一個(gè)類(lèi)中。例如,我們可以設計一個(gè)類(lèi): 
                      class CSmartReader 
                      { 
                      private: 
                      SCARDCONTEXT hSC; 
                      LONG lReturn; 
                      char mszReaders[1024]; 
                      LPTSTR pReader, pReaderName[2]; 
                      DWORD dwLen; 
                      int nReaders, nCurrentReader; 
                      SCARDHANDLE hCardHandle[2]; 
                      DWORD dwAP; 
                      public: 
                      CSmartReader(); //建立上下文、取讀卡器列表 
                      ~CSmartReader(); //釋放上下文 
                      void SetCurrentReader(int currentReader); 
                      int GetReaders(); //獲得讀卡器數目 
                      int ConnectReader(); //與當前讀卡器建立連接 
                      int DisConnectReader(); //與當前讀卡器斷開(kāi)連接 
                      int SendCommand(BYTE command[], int commandLength, BYTE result[], int *resultLength); //向讀卡器發(fā)送命令,并接收返回的數據。返回值為sw 
                      };

                      這樣,我們就可以方便地使用PC/SC接口了。

                  本文關(guān)鍵詞:智能卡,接口,讀卡器
                  回到頂部
                  99久热只有精品视频在线17_精品一区二区三区自拍图片_最新国产v亚洲_久久综合九色综合久
                  <strike id="tpvd9"><dfn id="tpvd9"></dfn></strike>

                        <em id="tpvd9"></em>

                          <address id="tpvd9"></address>
                            <dfn id="tpvd9"><sub id="tpvd9"></sub></dfn>

                            <thead id="tpvd9"><noframes id="tpvd9">
                            <ruby id="tpvd9"></ruby>

                                  <thead id="tpvd9"></thead>