อ่านบัตรประชาชน smartcard โดยใช้ python
ผมเขียนเรื่องนี้สำหรับเป็น 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”)
ส่วนนี้แค่ไล่อ่านจนครบทุกข้อมูล จริง ๆ จะมีรูปภาพอีกครับแต่ไม่ได้ทำไว้เพราะอายุบัตรค่อนข้างนาน
รูปในบัตรจะดูห่างจากตัวจริงเยอะไป
เยี่ยมมากครับ อธิบายแบบบ้านๆ แต่เห็นภาพชัดเจน
ขอคำสั่งดึงรูปด้วยครับ ขอบคุณครับ
@สุกิจ
http://www.codeproject.com/Articles/16653/A-Smart-Card-Framework-for-NET
http://www.aspfree.com/c/a/.NET/Smart-Cards-in-.NET/
แฮะ ๆ จำไม่ได้เหมือนกันครับ ลองดูจากโค้ด .net นะครับมันใช้คำสั่งเดียวกัน
@naminator
ขอบคุณมากครับ
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
ทราบได้อย่างไรครับว่า
บัตรประชาชไทยคือ ต้องอ่านค่านี้ 0xA0, 0x00, 0x00, 0x00, 0x54, 0x48, 0x00, 0x01
ผมพยายาม หาเอกสารมาตอบตัวเอง ยังหาไม่เจอ.
ผมก็ไม่ทราบเหมือนกันครับ เคยจะหาที่มาอยู่เหมือนกันเจอแต่เป็นโปรแกรมเหมือนทำ brute force ไปเรื่อย ๆ ครับ
อาจจะใช้วิธีนี้ก็ได้ครับ
เยี่ยมครับ ได้รหัส 16 บิตไปเปิดได้เลย