Skip to content

Instantly share code, notes, and snippets.

@gazambuja
Last active June 6, 2018 14:53
Show Gist options
  • Save gazambuja/79ee1c7b11d60ef82a595ab57a687c6f to your computer and use it in GitHub Desktop.
Save gazambuja/79ee1c7b11d60ef82a595ab57a687c6f to your computer and use it in GitHub Desktop.
#!/usr/bin/python
import json
from smartcard.CardType import ATRCardType
from smartcard.CardRequest import CardRequest
from smartcard.CardConnection import CardConnection
from smartcard.util import toBytes
action = error = False
jsonarr = []
# Establezco los comandos APDU utilizados en el documento de identidad uruguayo, estos datos se encuentran en la documentacion ofrecida por AGESIC:
GET_RESPONSE = [0x00, 0xB0]
SELECT = [0x00, 0xA4, 0x04, 0x00, 0x0C, 0xA0, 0x00, 0x00, 0x00, 0x18, 0x40, 0x00, 0x00, 0x01, 0x63, 0x42, 0x00, 0x00]
USERID = [0x00, 0xA4, 0x00, 0x00, 0x02, 0x70, 0x02]
# Funcion simple para mostrar la salida en formato json:
def output(data, error = False):
print json.dumps({'data': data})
exit()
# Los datos son devueltos como hexa, hay que convertirlos a ASCII:
def toUnicode(data):
result = ''
if isinstance(data, list):
for d in data:
result += unicode(chr(d),"utf-8")
else :
result = data
return result.encode('ascii',errors='ignore').replace(u"\u0011", "").replace(u"\u0017", "").strip()
# Envio un comando a la tarjeta:
def runCommand(cmd):
data, sw1, sw2 = cardservice.connection.transmit(cmd)
return [data, sw1, sw2];
# Ejecuto un comando y solicito y devuelvo la respuesta:
def getData(cmd, offset):
data, sw1, sw2 = runCommand(cmd)
data, sx1, sx2 = runCommand(GET_RESPONSE + offset + [sw2])
if( len(data) == 0 ):
return [False, False, False]
else :
nextOffset = data[2] + 3
return [data, data[1], nextOffset];
# Transformo los datos obtenidos en formato ASCII y los agrego a la lista 'jsonarr':
def addToJson(data, tag, offset):
datastring = toUnicode( data[3:data[2] + 3] )
if( datastring != '' ):
jsonarr.append("\"tag" + hex(tag) + "\":\"" + datastring + "\"")
# Este es el loop principal que revisa cada dato de la memoria de la tarjeta:
def getUserData():
lastOffset = 0x00
while True:
data, tag, nextOffset = getData( USERID, [0x00, lastOffset] )
if ( data == False and tag == False and nextOffset == False ) :
break
else :
addToJson(data, tag, lastOffset)
lastOffset = lastOffset + nextOffset
if ( len(jsonarr) > 0 ):
return jsonarr
else:
return False
# Aguardo a que sea insertada una tarjeta valida, me conecto a ella (SELECT), y obtengo los datos del usuario (getUserData)
def showInfo():
global cardservice
cardservice = cardrequest.waitforcard()
cardservice.connection.connect( CardConnection.T0_protocol )
runCommand( SELECT )
jsonOutput = getUserData()
output(jsonOutput)
# Me conecto al lector, le digo el codigo de la eCI uruguaya para aceptar unicamente estos chips, y le digo que aguarde 20 segundos. Si en ese tiempo no se inserta una cedula valida, dara error.
cardtype = ATRCardType( toBytes( "3B 7F 94 00 00 80 31 80 65 B0 85 03 00 EF 12 0F FF 82 90 00" ) ) # Solo eCI de UY
cardrequest = CardRequest( timeout=20, cardType=cardtype )
if (len(cardrequest.getReaders()) == 0 ):
output(False,"Lector no conectado")
else:
showInfo()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment