Home > Programming > อ่านบัตรประชาชน smartcard โดยใช้ python

อ่านบัตรประชาชน smartcard โดยใช้ python

February 8th, 2015

ผมเขียนเรื่องนี้สำหรับเป็น guideline สำหรับคนที่อยากอ่านข้อมูลในบัตรประชาชนนะครับ

ข้อมูลทั้งหมดได้มาจากคุณพุฒิพงศ์ ซึ่งเป็นคนพัฒนาโปรแกรม นี้ ครับ

ผมเมลไปถามแกหน้าด้าน ๆ เลยครับว่าทำยังไง แกก็ตอบมาแบบละเอียดเลยครับ

เลยไหน ๆ ก็ไหน ๆ ละขอเขียนทิ้งไว้ก็แล้วกันครับเผื่อมีคนอยากทราบวิธี

ผมใช้ lib ของ python pyscard ครับ วิธีการใช้ดูจาก documentation เลยครับ

ตัวอย่างเป็นการอ่านข้อมูลในส่วน public ของ smart card

# -*- coding: cp874 -*-
from smartcard.CardConnection import CardConnection
from smartcard.CardType import AnyCardType
from smartcard.CardRequest import CardRequest
from smartcard.util import toHexString, toBytes

import ธรรมดาครับ

cardtype = AnyCardType()
cardrequest = CardRequest( timeout=1, cardType=cardtype )

cardservice = cardrequest.waitforcard()

cardservice.connection.connect()

เชื่อมต่อไปยัง reader ดูว่ามีการ์ดเสียบอยู่นะ

SELECT = [0x00, 0xA4, 0x04, 0x00, 0x08]
THAI_ID_CARD = [0xA0, 0x00, 0x00, 0x00, 0x54, 0x48, 0x00, 0x01]
REQ_CID = [0x80, 0xb0, 0x00, 0x04, 0x02, 0x00, 0x0d]
REQ_THAI_NAME = [0x80, 0xb0, 0x00, 0x11, 0x02, 0x00, 0x64]
REQ_ENG_NAME = [0x80, 0xb0, 0x00, 0x75, 0x02, 0x00, 0x64]
REQ_GENDER = [0x80, 0xb0, 0x00, 0xE1, 0x02, 0x00, 0x01]
REQ_DOB = [0x80, 0xb0, 0x00, 0xD9, 0x02, 0x00, 0x08]
REQ_ADDRESS = [0x80, 0xb0, 0x15, 0x79, 0x02, 0x00, 0x64]
REQ_ISSUE_EXPIRE = [0x80, 0xb0, 0x01, 0x67, 0x02, 0x00, 0x12]

DATA = [REQ_CID,REQ_THAI_NAME,REQ_ENG_NAME,REQ_GENDER,REQ_DOB,
REQ_ADDRESS,REQ_ISSUE_EXPIRE]

ตรงนี้เป็นคำสั่งในการขอข้อมูลครับ คือ ขั้นตอนการขอข้อมูลจากการ์ดจะเป็น

1. ฉันจะอ่านบัตรประชาชนนะนายใช่บัตรประชาชนรึเปล่า
2. บัตรตอบมาว่าใช่หรือไม่
3. โอเค ฉันอยากได้ข้อมูลเลข 13 หลักที่มีความยาว x
4. บัตรตอบกลับมาว่าฉันมีข้อมูลนี้ ยาว x
5. ขอดูข้อมูลหน่อยละกัน
6. บัตรส่งข้อมูลให้

apdu = SELECT+THAI_ID_CARD
f = open(‘temp.txt’,’w’)

response, sw1, sw2 = cardservice.connection.transmit( apdu )
#print ‘response: ‘, response, ‘ status words: ‘, “%x %x” % (sw1, sw2)

อันนี้เป็นข้อ 1-2 ครับ ดูตรง sw1 กับ sw2 ครับ ถ้าโอเคจะตอบกลับมาเป็น

0x90 xx หรือ 0x61 xx ซึ่ง 90 คือโอเค ส่วน 61 คือ โอเคแต่มีข้อมูล xx ไบต์นะ

#print ‘response: ‘, response, ‘ status words: ‘, “%x %x” % (sw1, sw2)
for d in DATA:
response, sw1, sw2 = cardservice.connection.transmit( d )
print sw1
if sw1 == 0x61:

ไล่ขอข้อมูลใน list DATA ส่วนนี้สังเกตว่าบัตรตอบกลับมาว่า 0x61 มีข้อมูลอีก xx นะ
เริ่มจาก cid

GET_RESPONSE = [0X00, 0XC0, 0x00, 0x00 ]
apdu = GET_RESPONSE + [sw2]

ตรงนี้ขอดูข้อมูลที่บอกว่ามีหน่อย

print ‘sending ‘ + toHexString(apdu)
response, sw1, sw2 = cardservice.connection.transmit( apdu )
print ‘response: ‘, toHexString(response), ‘ status words: ‘, “%x %x” % (sw1, sw2)
result = “”
for i in response:
result = result+chr(i)
f.write(result.strip()+”\n”)

ส่วนนี้แค่ไล่อ่านจนครบทุกข้อมูล จริง ๆ จะมีรูปภาพอีกครับแต่ไม่ได้ทำไว้เพราะอายุบัตรค่อนข้างนาน

รูปในบัตรจะดูห่างจากตัวจริงเยอะไป


Categories: Programming Tags:
  1. Mr.P
    September 10th, 2015 at 11:00 | #1

    เยี่ยมมากครับ อธิบายแบบบ้านๆ แต่เห็นภาพชัดเจน

  2. สุกิจ
    October 4th, 2015 at 11:08 | #2

    ขอคำสั่งดึงรูปด้วยครับ ขอบคุณครับ

  3. naminator
    October 8th, 2015 at 13:27 | #3

    @สุกิจ
    http://www.codeproject.com/Articles/16653/A-Smart-Card-Framework-for-NET
    http://www.aspfree.com/c/a/.NET/Smart-Cards-in-.NET/

    แฮะ ๆ จำไม่ได้เหมือนกันครับ ลองดูจากโค้ด .net นะครับมันใช้คำสั่งเดียวกัน

  4. สุกิจ
    October 8th, 2015 at 13:52 | #4

    @naminator
    ขอบคุณมากครับ

  5. Sijan
    November 5th, 2015 at 14:24 | #5

    Hello, the code is perfectly written. I also want to know how to get image. I dont know the procedure to get the image and dump in a file , if possilbe let me know. Thanks and regards

  6. Mesa Dirmas
    March 2nd, 2016 at 15:58 | #6

    ทราบได้อย่างไรครับว่า
    บัตรประชาชไทยคือ ต้องอ่านค่านี้ 0xA0, 0x00, 0x00, 0x00, 0x54, 0x48, 0x00, 0x01
    ผมพยายาม หาเอกสารมาตอบตัวเอง ยังหาไม่เจอ.

    • naminator
      April 15th, 2016 at 18:19 | #7

      ผมก็ไม่ทราบเหมือนกันครับ เคยจะหาที่มาอยู่เหมือนกันเจอแต่เป็นโปรแกรมเหมือนทำ brute force ไปเรื่อย ๆ ครับ
      อาจจะใช้วิธีนี้ก็ได้ครับ

  7. Sarawut
    September 18th, 2016 at 21:45 | #8

    เยี่ยมครับ ได้รหัส 16 บิตไปเปิดได้เลย

Comments are closed.