python基於PCSC協議實現讀卡器和卡片通訊
阿新 • • 發佈:2018-12-25
簡介
PCSC協議是windows平臺下的一套通用API, 所 有 函 數 的 原 型 都 winscard.h中宣告,應用程式需要包含winscard.lib,所有函式的正常返回值都 SCARD_S_SUCCESS。它為讀卡器/卡片和電腦提供了一個標準介面,實現不同生產商的卡片和讀卡器之間的互操作性。之前工作中使用的時候是在VC++環境下之間呼叫的winscard提供的api,學了python之後試著用python來實現。 python由好個模組封裝了PCSC的介面,比如:PySmartCard/pyscard,我是試用了PySmartCard,後面的程式碼也是基於PySmartCard模組編寫的。
PySmartCard模組
下載地址:
需要先pip安裝這個模組,命令如下:
pip install PySmartCard
PySmartCard模組是PCSC/D8/D6/T6都支援的,我只用了PCSC。
實現程式碼
執行程式碼前需要連線上讀卡器,win10下讀卡器驅動貌似是預設安裝的。
#encoding=utf-8 #匯入PcscReader類 from PySmartCard.CpuCard import PcscReader #匯入time模組 import time def showLog(data, issend): '''列印日誌函式''' current = time.strftime('%Y_%m_%d %H:%M:%S', time.localtime()) if issend:#傳送到卡片的資料 send = '-->' else:#卡片返回的資料 send = '<--' print("{} {} {}".format(current, send, data)) def sendApdu(reader, apdu, recv_list, readerType=None): '''給卡片傳送指令的函式''' #清空 recv_list[:] = [] #去掉多餘的空格 apdu = apdu.replace(' ','') showLog(apdu, True) respone = reader.send_apdu(apdu,readerType) showLog(respone, False) #recv_list第1個元素是返回資料 recv_list.append(respone[:-4]) #recv_list第2個元素是sw recv_list.append(respone[-4:]) def sendApduCommand(reader, apdu, recv_list, readerType=None): '''完整的傳送指令函式''' sendApdu(reader, apdu, recv_list, readerType) #如果是返回的SW是6CXX或者61XX,重新發指令 apdu = apdu.replace(' ','') if recv_list[-1][:2] == '61': apdu = '00C00000' + recv_list[-1][2:4] sendApdu(reader, apdu, recv_list, readerType) elif recv_list[-1][:2].upper() == '6C': apdu = apdu[:8] + recv_list[-1][2:4] sendApdu(reader, apdu, recv_list, readerType) '''例項化PCSC讀卡器''' pcsc = PcscReader() '''獲取所有的讀卡器列表''' readerName = pcsc.get_pcsc_readerlist() ##print(readerName)#字串型別的讀卡器名稱,按;隔開 #按;切割字串,得到所有的讀卡器名稱 print('當前連線的讀卡器有:') readerNameList = readerName.split(';') for i in range(len(readerNameList)-1): print("{} {} :{}".format('reader',i,readerNameList[i])) '''連線指定的讀卡器''' print('*'*40) #要連線的讀卡器 useReaderName = "SCM Microsystems Inc. SDI010 Contactless Reader 0" useReaderName = "SCM Microsystems Inc. SDI010 Smart Card Reader 0" #得到的是字串型別的復位資訊 ATR = pcsc.connect_device(useReaderName) if ATR: print("ConnectDevice Success...") print("ATR: ", ATR) else: print("ConnectDevice Failed!") '''上電''' print('*'*40) #通訊介面型別: 1-contact reader 2-contactless reader readerType = 1 if 'Contactless'.lower() in useReaderName.lower(): readerType = 2 if 0== pcsc.power_on(readerType): print("Device PowerOn Success...") else: print("Device PowerOn Failed!") '''傳送APDU''' print('*'*40) apdu = '00A4 0400 00' recv_list = [] sendApduCommand(pcsc,apdu, recv_list, readerType) if recv_list[1] !="9000": print("Send Apdu Failed!") apdu = '0084 0000 08' recv_list = [] sendApduCommand(pcsc,apdu, recv_list, readerType) if recv_list[1] !="9000": print("Send Apdu Failed!") '''斷開讀卡器連線''' pcsc.disconnect_device() '''SM4_ECB加密計算''' print('*'*40) encrypt = pcsc.sm4_ecb('0123456789ABCDEFFEDCBA9876543210',\ '0123456789ABCDEFFEDCBA9876543210',1) print(encrypt)
執行結果: