Last active
June 6, 2018 14:53
-
-
Save gazambuja/79ee1c7b11d60ef82a595ab57a687c6f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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