SmartCard学习之PySmartCard

本文介绍了使用PySmartCard库成功操作FM1216-109 CPU卡的过程,重点在于MF下二进制文件的读写及外部密钥验证。操作流程包括连接、获取随机数、DES加密和文件操作,send_apdu函数在此过程中起到关键作用。需要注意PyDes库中byte array输入输出和padding mode的设置。
AI助手已提取文章相关产品:

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( )



您可能感兴趣的与本文相关内容

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值