python基于PCSC协议实现读卡器和卡片通信

简介

    PCSC协议是windows平台下的一套通用API, 所 有 函 数 的 原 型 都 winscard.h中声明,应用程序需要包含winscard.lib,所有函数的正常返回值都 SCARD_S_SUCCESS。它为读卡器/卡片和电脑提供了一个标准接口,实现不同生产商的卡片和读卡器之间的互操作性。之前工作中使用的时候是在VC++环境下之间调用的winscard提供的api,学了python之后试着用python来实现。     python由好个模块封装了PCSC的接口,比如:PySmartCard/pyscard,我是试用了PySmartCard,后面的代码也是基于PySmartCard模块编写的。

PySmartCard模块

下载地址:

https://pypi.org/project/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)

运行结果:

猜你喜欢

转载自blog.csdn.net/kongsuhongbaby/article/details/84776535