sudo apt update
sudo apt install -y python3 python3-pip python3-dev libccid pcscd libdbus-1-dev
sudo -H python3 -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pip --upgrade
sudo pip install pydes
sudo pip install PySmartCard
下面这个代码用来操作复旦的FM1216-109型号的CPU卡成功了,这段代码主要是实现MF下二进制文件的读写,外部密钥的校验。
其实没啥,主要看一下流程:
连接 ==》 获取随机数 ==》 des加密 ==》 文件操作
这样一个流程其实主要开始靠send_apdu()这个函数。
这边没写的是发卡的一个流程,其实类似,区别就是send_apdu里面发送的apdu不同。具体可以参考前面写的一些手动操作示例。
里面还有个坑就是PyDes的操作,需要注意输入输出数据是byte array, padding mode也是个坑。
that’s all !
from PySmartCard.CpuCard import PcscReader
import time
def showlog(data, send):
current = time.strftime('%Y_%m_%d %H:%M:%S', time.localtime())
if send:
send = '==>\t'
else:
send = '\t<=='
print("{} {} {}".format(current, send, data))
def sendApdu(reader, apdu, recv_list, readerType):
recv_list[:] = []
apdu = apdu.replace('','')
showlog(apdu, True)
response = reader.send_apdu(apdu, readerType)
showlog(response, False)
recv_list.append(response[:-4])
recv_list.append(response[-4:])
# checkError(recv_list)
#def checkError(recv_list):
if recv_list[-1][:2] == '61':
apdu = '00C00000' + recv_list[-1][2:4]
sendApdu(reader, apdu, recv_list, readerType)
elif recv_list[1] == '9000':
if len(recv_list[0]) > 0:
showlog(recv_list[0], False)
showlog(9000, False)
print("\tSend Apdu Succeed!\n")
else:
print("\tSend Apdu Failed!\n")
return -1
print("Test FM1216-109:")
pcsc = PcscReader()
result = pcsc.get_pcsc_readerlist()
#print("result: ",result)
readerNameList = result.split(";")
print("Current Card Reader:")
for i in range(len(readerNameList) - 1):
print("\t{}[{}]: {}".format('reader', i, readerNameList[i]))
readerName = "Dell Dell Smart Card Reader Keyboard 00 00"
result = pcsc.connect_device(readerName);
if len(result) == 0:
showlog = "{}: {} does not have samrt card".format("reader",
readerName)
print(showlog)
else:
print("connect succeed: ", readerName)
print("\tATR:", result)
#select the card's MD
print("select the card's MD: ")
readerType = 1 #reader type 1: connect-able reader
apdu = "00A4000000"
recv_list = []
sendApdu(pcsc, apdu, recv_list, readerType)
#CMD: get 8 bytes random number from card
apdu = "0084000008"
recv_list = []
sendApdu(pcsc, apdu, recv_list, readerType)
print("get Random Number: \n\t\t", recv_list[0])
randomNoStr = []
randomNoStr=bytearray.fromhex(recv_list[0])
print("\t", randomNoStr)
#use DES cipher
from pyDes import CBC,des,PAD_PKCS5,PAD_NORMAL
import binascii
key = "1234567812345678"
key = bytearray.fromhex(key)
print("key: \t", key, " len: ", len(key))
iv = b"\0\0\0\0\0\0\0\0"
deser = des(key, CBC, iv, pad=None, padmode=PAD_NORMAL)
print("randomNoStr: \t", randomNoStr, " len: ", len(randomNoStr))
cipherText = deser.encrypt(randomNoStr)
print("cipherText: \t", cipherText, " len: ", len(cipherText))
#import array
print("\tb2a_hex: \t", binascii.b2a_hex(cipherText), " len: ", len(cipherText))
clearText = deser.decrypt(cipherText)
print("clearText: \t", binascii.b2a_hex(clearText))
#send the DES encrypted random number to card
print("Send ciphertext to card: ")
apdu = "0082000008" + str(binascii.b2a_hex(cipherText), encoding='utf-8')
recv_list = []
sendApdu(pcsc, apdu, recv_list, readerType)
#select file NO. 16
print("\nselect NO.16 file: ")
apdu = "00A40000020016"
recv_list = []
sendApdu(pcsc, apdu, recv_list, readerType)
#write 8 bytes 1122334455667788 into file NO. 16
print("\nwrite the first 8 bytes with 0x1122334455667788: ")
apdu = "00D60000081122334455667788"
recv_list = []
sendApdu(pcsc, apdu, recv_list, readerType)
#read the first 8 bytes from NO. 16
print("\nread the first 8 bytes: ")
apdu = "00B0000008"
recv_list = []
sendApdu(pcsc, apdu, recv_list, readerType)
pcsc.disconnect_device( )
本文介绍了使用PySmartCard库成功操作FM1216-109 CPU卡的过程,重点在于MF下二进制文件的读写及外部密钥验证。操作流程包括连接、获取随机数、DES加密和文件操作,send_apdu函数在此过程中起到关键作用。需要注意PyDes库中byte array输入输出和padding mode的设置。
1642

被折叠的 条评论
为什么被折叠?



