from __future__ import print_function
from time import sleep
from smartcard.CardMonitoring import CardMonitor, CardObserver
#from smartcard.util import toHexString
import binascii
import io
import os
import sys
from PIL import Image
from smartcard.System import readers
from smartcard.util import HexListToBinString, toHexString, toBytes
class MyReader():
# Check card
SELECT = [0x00, 0xA4, 0x04, 0x00, 0x08]
THAI_CARD = [0xA0, 0x00, 0x00, 0x00, 0x54, 0x48, 0x00, 0x01]
# CID
CMD_CID = [0x80, 0xb0, 0x00, 0x04, 0x02, 0x00, 0x0d]
# TH Fullname
CMD_THFULLNAME = [0x80, 0xb0, 0x00, 0x11, 0x02, 0x00, 0x64]
# EN Fullname
CMD_ENFULLNAME = [0x80, 0xb0, 0x00, 0x75, 0x02, 0x00, 0x64]
# Date of birth
CMD_BIRTH = [0x80, 0xb0, 0x00, 0xD9, 0x02, 0x00, 0x08]
# Gender
CMD_GENDER = [0x80, 0xb0, 0x00, 0xE1, 0x02, 0x00, 0x01]
# Card Issuer
CMD_ISSUER = [0x80, 0xb0, 0x00, 0xF6, 0x02, 0x00, 0x64]
# Issue Date
CMD_ISSUE = [0x80, 0xb0, 0x01, 0x67, 0x02, 0x00, 0x08]
# Expire Date
CMD_EXPIRE = [0x80, 0xb0, 0x01, 0x6F, 0x02, 0x00, 0x08]
# Address
CMD_ADDRESS = [0x80, 0xb0, 0x15, 0x79, 0x02, 0x00, 0x64]
# Photo_Part1/20
CMD_PHOTO1 = [0x80, 0xb0, 0x01, 0x7B, 0x02, 0x00, 0xFF]
# Photo_Part2/20
CMD_PHOTO2 = [0x80, 0xb0, 0x02, 0x7A, 0x02, 0x00, 0xFF]
# Photo_Part3/20
CMD_PHOTO3 = [0x80, 0xb0, 0x03, 0x79, 0x02, 0x00, 0xFF]
# Photo_Part4/20
CMD_PHOTO4 = [0x80, 0xb0, 0x04, 0x78, 0x02, 0x00, 0xFF]
# Photo_Part5/20
CMD_PHOTO5 = [0x80, 0xb0, 0x05, 0x77, 0x02, 0x00, 0xFF]
# Photo_Part6/20
CMD_PHOTO6 = [0x80, 0xb0, 0x06, 0x76, 0x02, 0x00, 0xFF]
# Photo_Part7/20
CMD_PHOTO7 = [0x80, 0xb0, 0x07, 0x75, 0x02, 0x00, 0xFF]
# Photo_Part8/20
CMD_PHOTO8 = [0x80, 0xb0, 0x08, 0x74, 0x02, 0x00, 0xFF]
# Photo_Part9/20
CMD_PHOTO9 = [0x80, 0xb0, 0x09, 0x73, 0x02, 0x00, 0xFF]
# Photo_Part10/20
CMD_PHOTO10 = [0x80, 0xb0, 0x0A, 0x72, 0x02, 0x00, 0xFF]
# Photo_Part11/20
CMD_PHOTO11 = [0x80, 0xb0, 0x0B, 0x71, 0x02, 0x00, 0xFF]
# Photo_Part12/20
CMD_PHOTO12 = [0x80, 0xb0, 0x0C, 0x70, 0x02, 0x00, 0xFF]
# Photo_Part13/20
CMD_PHOTO13 = [0x80, 0xb0, 0x0D, 0x6F, 0x02, 0x00, 0xFF]
# Photo_Part14/20
CMD_PHOTO14 = [0x80, 0xb0, 0x0E, 0x6E, 0x02, 0x00, 0xFF]
# Photo_Part15/20
CMD_PHOTO15 = [0x80, 0xb0, 0x0F, 0x6D, 0x02, 0x00, 0xFF]
# Photo_Part16/20
CMD_PHOTO16 = [0x80, 0xb0, 0x10, 0x6C, 0x02, 0x00, 0xFF]
# Photo_Part17/20
CMD_PHOTO17 = [0x80, 0xb0, 0x11, 0x6B, 0x02, 0x00, 0xFF]
# Photo_Part18/20
CMD_PHOTO18 = [0x80, 0xb0, 0x12, 0x6A, 0x02, 0x00, 0xFF]
# Photo_Part19/20
CMD_PHOTO19 = [0x80, 0xb0, 0x13, 0x69, 0x02, 0x00, 0xFF]
# Photo_Part20/20
CMD_PHOTO20 = [0x80, 0xb0, 0x14, 0x68, 0x02, 0x00, 0xFF]
# Get all the available readers
# Thailand ID Smartcard
def thai2unicode(data):
result = ''
result = bytes(data).decode('tis-620')
return result.strip();
def getData(cmd, req = [0x00, 0xc0, 0x00, 0x00]):
data, sw1, sw2 = connection.transmit(cmd)
data, sw1, sw2 = connection.transmit(req + [cmd[-1]])
return [data, sw1, sw2];
def getData2(connection, cmd, req = [0x00, 0xc0, 0x00, 0x00]):
data, sw1, sw2 = self.connection.transmit(cmd)
data, sw1, sw2 = self.connection.transmit(req + [cmd[-1]])
return [data, sw1, sw2];
def __init__(self):
readerList = readers()
print ('Available readers:')
for readerIndex,readerItem in enumerate(readerList):
print(readerIndex, readerItem)
# Select reader
readerSelectIndex = 0 #int(input("Select reader[0]: ") or "0")
reader = readerList[readerSelectIndex]
print ("Using:", reader)
connection = reader.createConnection()
connection.connect()
atr = connection.getATR()
print ("ATR: " + toHexString(atr))
if (atr[0] == 0x3B & atr[1] == 0x67):
req = [0x00, 0xc0, 0x00, 0x01]
else :
req = [0x00, 0xc0, 0x00, 0x00]
# Check card
data, sw1, sw2 = connection.transmit(self.SELECT + self.THAI_CARD)
print ("Select Applet: %02X %02X" % (sw1, sw2))
# CID
#data = self.getData(self.CMD_CID, req)
#cid = self.thai2unicode(data[0])
data, sw1, sw2 = connection.transmit(self.CMD_CID)
data, sw1, sw2 = connection.transmit(req + [self.CMD_CID[-1]])
result = bytes(data).decode('tis-620')
myfinal = result.strip();
print ("CID: " + myfinal)
#cid = myfinal
# TH Fullname
#data = self.getData(self.CMD_THFULLNAME, req)
#print ("TH Fullname: " + self.thai2unicode(data[0]))
data, sw1, sw2 = connection.transmit(self.CMD_THFULLNAME)
data, sw1, sw2 = connection.transmit(req + [self.CMD_THFULLNAME[-1]])
result = bytes(data).decode('tis-620')
myfinal= result.strip();
print("TH Fullname: " + myfinal)
#print(thai2unicode2(data[0])))
# EN Fullname
#data = self.getData(self.CMD_ENFULLNAME, req)
#print ("EN Fullname: " + self.thai2unicode(data[0]))
data, sw1, sw2 = connection.transmit(self.CMD_ENFULLNAME)
data, sw1, sw2 = connection.transmit(req + [self.CMD_ENFULLNAME[-1]])
result = bytes(data).decode('tis-620')
myfinal= result.strip();
print("EN Fullname: " + myfinal)
# Date of birth
#data = self.getData(self.CMD_BIRTH, req)
#print( "Date of birth: " + self.thai2unicode(data[0]))
data, sw1, sw2 = connection.transmit(self.CMD_BIRTH)
data, sw1, sw2 = connection.transmit(req + [self.CMD_BIRTH[-1]])
result = bytes(data).decode('tis-620')
myfinal= result.strip();
print("Date of birth: " + myfinal)
# Gender
#data = self.getData(self.CMD_GENDER, req)
#print ("Gender: " + self.thai2unicode(data[0]))
data, sw1, sw2 = connection.transmit(self.CMD_GENDER)
data, sw1, sw2 = connection.transmit(req + [self.CMD_GENDER[-1]])
result = bytes(data).decode('tis-620')
myfinal= result.strip();
print("Gender: " + myfinal)
# Card Issuer
#data = self.getData(self.CMD_ISSUER, req)
#print ("Card Issuer: " + self.thai2unicode(data[0]))
data, sw1, sw2 = connection.transmit(self.CMD_ISSUER)
data, sw1, sw2 = connection.transmit(req + [self.CMD_ISSUER[-1]])
result = bytes(data).decode('tis-620')
myfinal= result.strip();
print("Card Issuer: " + myfinal)
# Issue Date
#data = self.getData(self.CMD_ISSUE, req)
#print ("Issue Date: " + self.thai2unicode(data[0]))
data, sw1, sw2 = connection.transmit(self.CMD_ISSUE)
data, sw1, sw2 = connection.transmit(req + [self.CMD_ISSUE[-1]])
result = bytes(data).decode('tis-620')
myfinal= result.strip();
print("Issue Date: " + myfinal)
# Expire Date
#data = self.getData(self.CMD_EXPIRE, req)
#print ("Expire Date: " + self.thai2unicode(data[0]))
data, sw1, sw2 = connection.transmit(self.CMD_EXPIRE)
data, sw1, sw2 = connection.transmit(req + [self.CMD_EXPIRE[-1]])
result = bytes(data).decode('tis-620')
myfinal= result.strip();
print("Expire Date: " + myfinal)
# Address
#data = self.getData(self.CMD_ADDRESS, req)
#print ("Address: " + self.thai2unicode(data[0]))
data, sw1, sw2 = connection.transmit(self.CMD_ADDRESS)
data, sw1, sw2 = connection.transmit(req + [self.CMD_ADDRESS[-1]])
result = bytes(data).decode('tis-620')
myfinal= result.strip();
print("Address: " + myfinal)
'''
# PHOTO
print("P1")
photo = self.getData2(connection, self.CMD_PHOTO1, req)[0]
print("P2")
photo += self.getData2(connection, self.CMD_PHOTO2, req)[0]
photo += self.getData2(connection, self.CMD_PHOTO3, req)[0]
photo += self.getData2(connection, self.CMD_PHOTO4, req)[0]
photo += self.getData2(connection, self.CMD_PHOTO5, req)[0]
photo += self.getData2(connection, self.CMD_PHOTO6, req)[0]
photo += self.getData2(connection, self.CMD_PHOTO7, req)[0]
photo += self.getData2(connection, self.CMD_PHOTO8, req)[0]
photo += self.getData2(connection, self.CMD_PHOTO9, req)[0]
photo += self.getData2(connection, self.CMD_PHOTO10, req)[0]
photo += self.getData2(sconnection, self.CMD_PHOTO11, req)[0]
photo += self.getData2(connection, self.CMD_PHOTO12, req)[0]
photo += self.getData2(connection, self.CMD_PHOTO13, req)[0]
photo += self.getData2(connection, self.CMD_PHOTO14, req)[0]
photo += self.getData2(connection, self.CMD_PHOTO15, req)[0]
photo += self.getData2(connection, self.CMD_PHOTO16, req)[0]
photo += self.getData2(connection, self.CMD_PHOTO17, req)[0]
photo += self.getData2(connection, self.CMD_PHOTO18, req)[0]
photo += self.getData2(connection, self.CMD_PHOTO19, req)[0]
photo += self.getData2(connection, self.CMD_PHOTO20, req)[0]
'''
"""
data, sw1, sw2 = connection.transmit(self.CMD_PHOTO1)
data, sw1, sw2 = connection.transmit(req + [self.CMD_PHOTO1[-1]])
photo = [data, sw1, sw2]
data, sw1, sw2 = connection.transmit(self.CMD_PHOTO2)
data, sw1, sw2 = connection.transmit(req + [self.CMD_PHOTO2[-1]])
photo += [data, sw1, sw2]
data, sw1, sw2 = connection.transmit(self.CMD_PHOTO3)
data, sw1, sw2 = connection.transmit(req + [self.CMD_PHOTO3[-1]])
photo += [data, sw1, sw2]
data, sw1, sw2 = connection.transmit(self.CMD_PHOTO4)
data, sw1, sw2 = connection.transmit(req + [self.CMD_PHOTO4[-1]])
photo += [data, sw1, sw2]
data, sw1, sw2 = connection.transmit(self.CMD_PHOTO5)
data, sw1, sw2 = connection.transmit(req + [self.CMD_PHOTO5[-1]])
photo += [data, sw1, sw2]
data, sw1, sw2 = connection.transmit(self.CMD_PHOTO6)
data, sw1, sw2 = connection.transmit(req + [self.CMD_PHOTO6[-1]])
photo += [data, sw1, sw2]
data, sw1, sw2 = connection.transmit(self.CMD_PHOTO7)
data, sw1, sw2 = connection.transmit(req + [self.CMD_PHOTO7[-1]])
photo += [data, sw1, sw2]
data, sw1, sw2 = connection.transmit(self.CMD_PHOTO8)
data, sw1, sw2 = connection.transmit(req + [self.CMD_PHOTO8[-1]])
photo += [data, sw1, sw2]
data, sw1, sw2 = connection.transmit(self.CMD_PHOTO9)
data, sw1, sw2 = connection.transmit(req + [self.CMD_PHOTO9[-1]])
photo += [data, sw1, sw2]
data, sw1, sw2 = connection.transmit(self.CMD_PHOTO10)
data, sw1, sw2 = connection.transmit(req + [self.CMD_PHOTO10[-1]])
photo += [data, sw1, sw2]
data, sw1, sw2 = connection.transmit(self.CMD_PHOTO11)
data, sw1, sw2 = connection.transmit(req + [self.CMD_PHOTO11[-1]])
photo += [data, sw1, sw2]
data, sw1, sw2 = connection.transmit(self.CMD_PHOTO12)
data, sw1, sw2 = connection.transmit(req + [self.CMD_PHOTO12[-1]])
photo += [data, sw1, sw2]
data, sw1, sw2 = connection.transmit(self.CMD_PHOTO13)
data, sw1, sw2 = connection.transmit(req + [self.CMD_PHOTO13[-1]])
photo += [data, sw1, sw2]
data, sw1, sw2 = connection.transmit(self.CMD_PHOTO14)
data, sw1, sw2 = connection.transmit(req + [self.CMD_PHOTO14[-1]])
photo += [data, sw1, sw2]
data, sw1, sw2 = connection.transmit(self.CMD_PHOTO15)
data, sw1, sw2 = connection.transmit(req + [self.CMD_PHOTO15[-1]])
photo += [data, sw1, sw2]
data, sw1, sw2 = connection.transmit(self.CMD_PHOTO16)
data, sw1, sw2 = connection.transmit(req + [self.CMD_PHOTO16[-1]])
photo += [data, sw1, sw2]
data, sw1, sw2 = connection.transmit(self.CMD_PHOTO17)
data, sw1, sw2 = connection.transmit(req + [self.CMD_PHOTO17[-1]])
photo += [data, sw1, sw2]
data, sw1, sw2 = connection.transmit(self.CMD_PHOTO18)
data, sw1, sw2 = connection.transmit(req + [self.CMD_PHOTO18[-1]])
photo += [data, sw1, sw2]
data, sw1, sw2 = connection.transmit(self.CMD_PHOTO19)
data, sw1, sw2 = connection.transmit(req + [self.CMD_PHOTO19[-1]])
photo += [data, sw1, sw2]
data, sw1, sw2 = connection.transmit(self.CMD_PHOTO20)
data, sw1, sw2 = connection.transmit(req + [self.CMD_PHOTO20[-1]])
photo += [data, sw1, sw2]
data = HexListToBinString(photo)
f = open(cid + ".jpg", "wb")
f.write (data)
f.close
print("Craete photo success.")
"""
# Exit program
connection.close()
reader.close()
# a simple card observer that prints inserted/removed cards
class PrintObserver(CardObserver):
"""A simple card observer that is notified
when cards are inserted/removed from the system and
prints the list of cards
"""
"""
readerList = readers()
reader = readerList[0]
connection = reader.createConnection()
"""
# Thailand ID Smartcard
# tis-620 to utf-8
def thai2unicode(data):
result = ''
if isinstance(data, list):
for d in data:
if (sys.version_info.major < 3):
result += unicode(chr(d),"tis-620")
else :
result += chr(d).decode("tis-620").encode("utf-8")
else :
result = data.decode("tis-620").encode("utf-8")
return result.strip();
def getData(cmd, req = [0x00, 0xc0, 0x00, 0x00]):
data, sw1, sw2 = self.connection.transmit(cmd)
data, sw1, sw2 = self.connection.transmit(req + [cmd[-1]])
return [data, sw1, sw2];
# define the APDUs used in this script
# https://github.com/chakphanu/ThaiNationalIDCard/blob/master/APDU.md
def update(self, observable, actions):
(addedcards, removedcards) = actions
for card in addedcards:
print("+Inserted: ", toHexString(card.atr))
myreader = MyReader()
for card in removedcards:
print("-Removed: ", toHexString(card.atr))
print("Please insert your card.")
if __name__ == '__main__':
result = ""
while True and result != "q":
#print("Insert or remove a smartcard in the system.")
#print("This program will exit in 10 seconds")
#print("")
cardmonitor = CardMonitor()
cardobserver = PrintObserver()
cardmonitor.addObserver(cardobserver)
#sleep(10)
# don't forget to remove observer, or the
# monitor will poll forever...
#cardmonitor.deleteObserver(cardobserver)
#import sys
#if 'win32' == sys.platform:
# print('press Enter to continue')
# sys.stdin.read(1)
#print("----------------------------------")
#print("Press 'q + enter' to quit program.")
#print("----------------------------------")
result = str(input(""))
if (result == "q"):
import sys
if 'win32' == sys.platform:
print('press Enter to continue')
sys.stdin.read(1)