Skip to content

Instantly share code, notes, and snippets.

@kangfend
Forked from bouroo/thai-id-card.py
Created October 19, 2018 08:12
Show Gist options
  • Save kangfend/e028aef791d9482463c7ee776c91b822 to your computer and use it in GitHub Desktop.
Save kangfend/e028aef791d9482463c7ee776c91b822 to your computer and use it in GitHub Desktop.
Thai National ID Card reader in python
#!/usr/bin/env python
# bouroo
# 17.07.2017
# apt-get install pcscd python-pyscard
import os
import io
#import Image
from smartcard.System import readers
import binascii
# Thailand ID Smartcard
# tis-620 to utf-8
def thai2unicode(data):
result = ''
if isinstance(data, list):
for d in data:
result += unicode(chr(d),"tis-620")
else :
result = data.decode("tis-620").encode("utf-8")
return result.strip();
# define the APDUs used in this script
# https://github.com/chakphanu/ThaiNationalIDCard/blob/master/APDU.md
# Reset
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]
GET_CID = [0x00, 0xc0, 0x00, 0x00, 0x0d]
# TH Fullname
CMD_THFULLNAME = [0x80, 0xb0, 0x00, 0x11, 0x02, 0x00, 0x64]
GET_THFULLNAME = [0x00, 0xc0, 0x00, 0x00, 0x64]
# EN Fullname
CMD_ENFULLNAME = [0x80, 0xb0, 0x00, 0x75, 0x02, 0x00, 0x64]
GET_ENFULLNAME = [0x00, 0xc0, 0x00, 0x00, 0x64]
# Date of birth
CMD_BIRTH = [0x80, 0xb0, 0x00, 0xD9, 0x02, 0x00, 0x08]
GET_BIRTH = [0x00, 0xc0, 0x00, 0x00, 0x08]
# Gender
CMD_GENDER = [0x80, 0xb0, 0x00, 0xE1, 0x02, 0x00, 0x01]
GET_GENDER = [0x00, 0xc0, 0x00, 0x00, 0x01]
# Card Issuer
CMD_ISSUER = [0x80, 0xb0, 0x00, 0xF6, 0x02, 0x00, 0x64]
GET_ISSUER = [0x00, 0xc0, 0x00, 0x00, 0x64]
# Issue Date
CMD_ISSUE = [0x80, 0xb0, 0x01, 0x67, 0x02, 0x00, 0x08]
GET_ISSUE = [0x00, 0xc0, 0x00, 0x00, 0x08]
# Expire Date
CMD_EXPIRE = [0x80, 0xb0, 0x01, 0x6F, 0x02, 0x00, 0x08]
GET_EXPIRE = [0x00, 0xc0, 0x00, 0x00, 0x08]
# Address
CMD_ADDRESS = [0x80, 0xb0, 0x15, 0x79, 0x02, 0x00, 0x64]
GET_ADDRESS = [0x00, 0xc0, 0x00, 0x00, 0x64]
# Photo_Part1/20
CMD_PHOTO1 = [0x80, 0xb0, 0x01, 0x7B, 0x02, 0x00, 0xFF]
GET_PHOTP1 = [0x00, 0xc0, 0x00, 0x00, 0xFF]
# Photo_Part2/20
CMD_PHOTO2 = [0x80, 0xb0, 0x02, 0x7A, 0x02, 0x00, 0xFF]
GET_PHOTP2 = [0x00, 0xc0, 0x00, 0x00, 0xFF]
# Photo_Part3/20
CMD_PHOTO3 = [0x80, 0xb0, 0x03, 0x79, 0x02, 0x00, 0xFF]
GET_PHOTP3 = [0x00, 0xc0, 0x00, 0x00, 0xFF]
# Photo_Part4/20
CMD_PHOTO4 = [0x80, 0xb0, 0x04, 0x78, 0x02, 0x00, 0xFF]
GET_PHOTP4 = [0x00, 0xc0, 0x00, 0x00, 0xFF]
# Photo_Part5/20
CMD_PHOTO5 = [0x80, 0xb0, 0x05, 0x77, 0x02, 0x00, 0xFF]
GET_PHOTP5 = [0x00, 0xc0, 0x00, 0x00, 0xFF]
# Photo_Part6/20
CMD_PHOTO6 = [0x80, 0xb0, 0x06, 0x76, 0x02, 0x00, 0xFF]
GET_PHOTP6 = [0x00, 0xc0, 0x00, 0x00, 0xFF]
# Photo_Part7/20
CMD_PHOTO7 = [0x80, 0xb0, 0x07, 0x75, 0x02, 0x00, 0xFF]
GET_PHOTP7 = [0x00, 0xc0, 0x00, 0x00, 0xFF]
# Photo_Part8/20
CMD_PHOTO8 = [0x80, 0xb0, 0x08, 0x74, 0x02, 0x00, 0xFF]
GET_PHOTP8 = [0x00, 0xc0, 0x00, 0x00, 0xFF]
# Photo_Part9/20
CMD_PHOTO9 = [0x80, 0xb0, 0x09, 0x73, 0x02, 0x00, 0xFF]
GET_PHOTP9 = [0x00, 0xc0, 0x00, 0x00, 0xFF]
# Photo_Part10/20
CMD_PHOTO10 = [0x80, 0xb0, 0x0A, 0x72, 0x02, 0x00, 0xFF]
GET_PHOTP10 = [0x00, 0xc0, 0x00, 0x00, 0xFF]
# Photo_Part11/20
CMD_PHOTO11 = [0x80, 0xb0, 0x0B, 0x71, 0x02, 0x00, 0xFF]
GET_PHOTP11 = [0x00, 0xc0, 0x00, 0x00, 0xFF]
# Photo_Part12/20
CMD_PHOTO12 = [0x80, 0xb0, 0x0C, 0x70, 0x02, 0x00, 0xFF]
GET_PHOTP12 = [0x00, 0xc0, 0x00, 0x00, 0xFF]
# Photo_Part13/20
CMD_PHOTO13 = [0x80, 0xb0, 0x0D, 0x6F, 0x02, 0x00, 0xFF]
GET_PHOTP13 = [0x00, 0xc0, 0x00, 0x00, 0xFF]
# Photo_Part14/20
CMD_PHOTO14 = [0x80, 0xb0, 0x0E, 0x6E, 0x02, 0x00, 0xFF]
GET_PHOTP14 = [0x00, 0xc0, 0x00, 0x00, 0xFF]
# Photo_Part15/20
CMD_PHOTO15 = [0x80, 0xb0, 0x0F, 0x6D, 0x02, 0x00, 0xFF]
GET_PHOTP15 = [0x00, 0xc0, 0x00, 0x00, 0xFF]
# Photo_Part16/20
CMD_PHOTO16 = [0x80, 0xb0, 0x10, 0x6C, 0x02, 0x00, 0xFF]
GET_PHOTP16 = [0x00, 0xc0, 0x00, 0x00, 0xFF]
# Photo_Part17/20
CMD_PHOTO17 = [0x80, 0xb0, 0x11, 0x6B, 0x02, 0x00, 0xFF]
GET_PHOTP17 = [0x00, 0xc0, 0x00, 0x00, 0xFF]
# Photo_Part18/20
CMD_PHOTO18 = [0x80, 0xb0, 0x12, 0x6A, 0x02, 0x00, 0xFF]
GET_PHOTP18 = [0x00, 0xc0, 0x00, 0x00, 0xFF]
# Photo_Part19/20
CMD_PHOTO19 = [0x80, 0xb0, 0x13, 0x69, 0x02, 0x00, 0xFF]
GET_PHOTP19 = [0x00, 0xc0, 0x00, 0x00, 0xFF]
# Photo_Part20/20
CMD_PHOTO20 = [0x80, 0xb0, 0x14, 0x68, 0x02, 0x00, 0xFF]
GET_PHOTP20 = [0x00, 0xc0, 0x00, 0x00, 0xFF]
# get all the available readers
r = readers()
print "Available readers:", r
reader = r[0]
print "Using:", reader
connection = reader.createConnection()
connection.connect()
# Reset
data, sw1, sw2 = connection.transmit(SELECT + THAI_CARD)
print "Select Applet: %02X %02X" % (sw1, sw2)
# CID
data, sw1, sw2 = connection.transmit(CMD_CID)
data, sw1, sw2 = connection.transmit(GET_CID)
print "CID: " + thai2unicode(data)
# TH Fullname
data, sw1, sw2 = connection.transmit(CMD_THFULLNAME)
data, sw1, sw2 = connection.transmit(GET_THFULLNAME)
print "TH Fullname: " + thai2unicode(data)
# EN Fullname
data, sw1, sw2 = connection.transmit(CMD_ENFULLNAME)
data, sw1, sw2 = connection.transmit(GET_ENFULLNAME)
print "EN Fullname: " + thai2unicode(data)
# Date of birth
data, sw1, sw2 = connection.transmit(CMD_BIRTH)
data, sw1, sw2 = connection.transmit(GET_BIRTH)
print "Date of birth: " + thai2unicode(data)
# Gender
data, sw1, sw2 = connection.transmit(CMD_GENDER)
data, sw1, sw2 = connection.transmit(GET_GENDER)
print "Gender: " + thai2unicode(data)
# Card Issuer
data, sw1, sw2 = connection.transmit(CMD_ISSUER)
data, sw1, sw2 = connection.transmit(GET_ISSUER)
print "Card Issuer: " + thai2unicode(data)
# Issue Date
data, sw1, sw2 = connection.transmit(CMD_ISSUE)
data, sw1, sw2 = connection.transmit(GET_ISSUE)
print "Issue Date: " + thai2unicode(data)
# Expire Date
data, sw1, sw2 = connection.transmit(CMD_EXPIRE)
data, sw1, sw2 = connection.transmit(GET_EXPIRE)
print "Expire Date: " + thai2unicode(data)
# Address
data, sw1, sw2 = connection.transmit(CMD_ADDRESS)
data, sw1, sw2 = connection.transmit(GET_ADDRESS)
print "Address: " + thai2unicode(data)
# PHOTO
data, sw1, sw2 = connection.transmit(CMD_PHOTO1)
data, sw1, sw2 = connection.transmit(GET_PHOTP1)
print data
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment