Commit f1245abd authored by Arturo Hernandez's avatar Arturo Hernandez
Browse files

working write, inc, dec & test

parent 41c2ecdf
......@@ -37,17 +37,17 @@ def card_start():
LOGGER.info('UUIDHex: {}'.format(toHexString(uid, 1)))
return card, atr, uid
def find_atr(data, atr):
""" requires data{ATR_match:[], ATR_possible:[]}"""
def find_atr(output, atr):
""" requires output{ATR_match:[], ATR_possible:[]}"""
found = parseATR.match_atr_differentiated(atr, "src/parseATR/smartcard_list.txt")
if found:
if atr in found:
for d in found[atr]:
data["ATR_match"].append(str(d))
output["ATR_match"].append(str(d))
del found[atr]
for a in found:
for d in found[a]:
data["ATR_possible"].append(str(d))
output["ATR_possible"].append(str(d))
class BaseHandler(tornado.web.RequestHandler):
def set_default_headers(self):
......@@ -85,7 +85,7 @@ class ReadCardHandler(BaseHandler):
self.write({"error": str(e)})
return
data = {
output = {
'reader': str(card.reader),
'ATR': atr,
'ATR_match': [],
......@@ -97,32 +97,40 @@ class ReadCardHandler(BaseHandler):
if block >=0:
LOGGER.info("reading block %i", block)
if card.auth_with_keys(block,key_a, key_b, use_keyb):
block_data = card.read_block(block)
data["data"]={
data = card.read_block(block)
output["data"]={
"block" : block,
"array" : block_data,
"hex": toHexString(block_data,1),
"string" : toHexString(block_data),
"array" : data,
"hex": toHexString(data,1),
"string" : toHexString(data),
"isValue": False,
"value": 0,
"isTrailer": (block & 0x03) == 0x03 if block < 128 else (block & 0x0F) == 0x0F,
}
#check if value
value = card.parse_value(block_data)
value = card.parse_value(data)
if value is not None:
data["data"]["isValue"] = True
data["data"]["value"] = value[0] #TODO: adr?
output["data"]["isValue"] = True
output["data"]["value"] = value[0]
output["data"]["value_adr"] = value[1]
else:
data["message"] = "Sin autorización para leer bloque de datos"
find_atr(data, atr)
self.write(data)
output["message"] = "Sin autorización para leer bloque de datos"
find_atr(output, atr)
self.write(output)
class WriteCardHandler(BaseHandler):
def post(self):
print("writing card...")
LOGGER.info("writing card...")
block = int(self.get_argument("block",strip=True))
data = list(bytes.fromhex(self.get_argument("data", strip=True)))
value = self.get_argument("value", default=None, strip=True)
value_adr = self.get_argument("value_adr", default=None, strip=True)
if value is not None and value_adr is not None:
#format value
value = int(value)
value_adr = int(value_adr)
data = OMNIKEYCard.format_value(value, value_adr)
else:
data = list(bytes.fromhex(self.get_argument("data", strip=True)))
key_a = self.get_argument("key_a", default=config.DEFAULT_KEY_A, strip=True)
key_b = self.get_argument("key_b", default=config.DEFAULT_KEY_B, strip=True)
use_keyb = config.str2bool(self.get_argument("use_keyb", default="False"))
......@@ -133,7 +141,7 @@ class WriteCardHandler(BaseHandler):
self.write({"error": str(e)})
return
data = {
output = {
'reader': str(card.reader),
'ATR': atr,
'ATR_match': [],
......@@ -146,9 +154,83 @@ class WriteCardHandler(BaseHandler):
if not card.auth_with_keys(block,key_a, key_b, use_keyb):
self.write({"error": "No se pudo autenticar"})
return
card.write_block(block,data)
find_atr(data, atr)
self.write(data)
card.write_block(block, data)
find_atr(output, atr)
self.write(output)
class IncrementValueHandler(BaseHandler):
def post(self):
LOGGER.info("increment card value...")
block = int(self.get_argument("block",strip=True))
value = self.get_argument("value", strip=True)
value = int(value)
key_a = self.get_argument("key_a", default=config.DEFAULT_KEY_A, strip=True)
key_b = self.get_argument("key_b", default=config.DEFAULT_KEY_B, strip=True)
use_keyb = config.str2bool(self.get_argument("use_keyb", default="False"))
try:
card, atr, uid = card_start()
except OMNIKEYException as e:
LOGGER.info("Error: {}".format(e))
self.write({"error": str(e)})
return
output = {
'reader': str(card.reader),
'ATR': atr,
'ATR_match': [],
'ATR_possible': [],
'UUIDHex': toHexString(uid, 1),
'message': 'OK'
}
LOGGER.info("Writing block %i", block)
if not card.auth_with_keys(block,key_a, key_b, use_keyb):
self.write({"error": "No se pudo autenticar"})
return
try:
card.increment_value(block, value)
except SWException as e:
self.write({"error": "No se pudo incrementar valor"})
return
find_atr(output, atr)
self.write(output)
class DecrementValueHandler(BaseHandler):
def post(self):
LOGGER.info("decrement card value...")
block = int(self.get_argument("block",strip=True))
value = self.get_argument("value", strip=True)
value = int(value)
key_a = self.get_argument("key_a", default=config.DEFAULT_KEY_A, strip=True)
key_b = self.get_argument("key_b", default=config.DEFAULT_KEY_B, strip=True)
use_keyb = config.str2bool(self.get_argument("use_keyb", default="False"))
try:
card, atr, uid = card_start()
except OMNIKEYException as e:
LOGGER.info("Error: {}".format(e))
self.write({"error": str(e)})
return
output = {
'reader': str(card.reader),
'ATR': atr,
'ATR_match': [],
'ATR_possible': [],
'UUIDHex': toHexString(uid, 1),
'message': 'OK'
}
LOGGER.info("Writing block %i", block)
if not card.auth_with_keys(block,key_a, key_b, use_keyb):
self.write({"error": "No se pudo autenticar"})
return
try:
card.decrement_value(block, value)
except SWException as e:
self.write({"error": "No se pudo decrementar valor"})
return
find_atr(output, atr)
self.write(output)
class InitCardHandler(BaseHandler):
""" WIP mf plus"""
......@@ -170,7 +252,8 @@ class InitCardHandler(BaseHandler):
#init stuff here!
card.APDU_get_version()
init = card.MP_BO_Init()
data = {
#TODO: init keys here?
output = {
'reader': str(card.reader),
'ATR': atr,
'ATR_match': [],
......@@ -179,8 +262,8 @@ class InitCardHandler(BaseHandler):
'message': 'OK',
'init': str(init)
}
find_atr(data, atr)
self.write(data)
find_atr(output, atr)
self.write(output)
class MainHandler(tornado.web.RequestHandler):
def get(self):
......@@ -204,7 +287,9 @@ def make_app():
(r"/api/?", TestHandler),
(r"/api/read-card/?", ReadCardHandler),
(r"/api/init-card/?", InitCardHandler),
(r"/api/write-card/?", MainHandler),
(r"/api/write-card/?", WriteCardHandler),
(r"/api/increment-value/?", IncrementValueHandler),
(r"/api/decrement-value/?", DecrementValueHandler),
(r"/mst_cert.crt()",tornado.web.StaticFileHandler, {"path": config.MST_CERT}),
(r"/(.*)",tornado.web.StaticFileHandler, {"path": "src/www"},), #path fixed to top
], template_path="src/www", debug=config.DEBUG) #path fixed to top
......
......@@ -153,12 +153,18 @@ class OMNIKEYCard(object):
v1 = block[:4]
v2 = block[4:8]
v3 = block[8:12]
if v2 == [255-v for v in v1] and v1 == v3 and block[12] == block[14] and block[13] == block[15] and 255 - block[12] == block[12]:
value = (unpack("<i",v1)[0], block[12])
LOGGER.debug("testing for v1={} v2={} v3={}".format(v1, v2, v3))
if v2 == [255-v for v in v1] and v1 == v3 and block[12] == block[14] and block[13] == block[15] and 255 - block[13] == block[12]:
value = (unpack("<i",bytes(v1))[0], block[12])
LOGGER.debug("value found!")
else:
LOGGER.debug("not a value block...")
return value
@staticmethod
def format_value(value, adr) -> list:
block = list(pack("<iiibbbb", value, ~value, value, adr, ~adr, adr, ~adr))
return block
def APDU_get_version(self) -> str:
data, sw1, sw2 = self.connection.transmit([0xFF, 0x68, 0x0E, 0x08, 0x02, 0x01, 0x00]) # propietary reader command "get version"
......@@ -274,7 +280,7 @@ class OMNIKEYCard(object):
raise OMNIKEYException("bloqueado acceso a llaves")
#TODO: check data size must be always 16
if len(data) != 16:
raise OMNIKEYException("tamaño de datos incorrecto")
raise OMNIKEYException("tamaño de datos incorrecto: {} {}".format(len(data), data))
response, sw1, sw2 = self.connection.transmit([0xFF, 0xD6, 0x00 , block, len(data)] + data) # read block
LOGGER.debug ("WB#{}, data:{}, sw {}". format(block, toHexString(data), toHexString([sw1, sw2])))
self.sw1 = sw1; self.sw2 = sw2
......@@ -307,9 +313,9 @@ class OMNIKEYCard(object):
LOGGER.debug ("Intentando escribir bloque de llaves #{}". format(block))
raise OMNIKEYException("bloqueado acceso a llaves")
#TODO: check value is int32
data = [ byte2int(x) for x in pack("I", value_inc)]
data = [ byte2int(x) for x in pack("<i", value_inc)]
response, sw1, sw2 = self.connection.transmit([0xFF, 0xD4, 0x00 , block, 4] + data) # read block
LOGGER.debug ("WB#{}, data:{}, sw {}". format(block, toHexString(data), toHexString([sw1, sw2])))
LOGGER.debug ("WI#{}, data:{}, sw {}". format(block, toHexString(data), toHexString([sw1, sw2])))
self.sw1 = sw1; self.sw2 = sw2
errorchain[0](response, sw1, sw2)
......@@ -318,9 +324,9 @@ class OMNIKEYCard(object):
LOGGER.debug ("Intentando escribir bloque de llaves #{}". format(block))
raise OMNIKEYException("bloqueado acceso a llaves")
#TODO: check value is int32
data = [ byte2int(x) for x in pack("I", value_dec)]
data = [ byte2int(x) for x in pack("<i", value_dec)]
response, sw1, sw2 = self.connection.transmit([0xFF, 0xD8, 0x00 , block, 4] + data) # read block
LOGGER.debug ("WB#{}, data:{}, sw {}". format(block, toHexString(data), toHexString([sw1, sw2])))
LOGGER.debug ("WD#{}, data:{}, sw {}". format(block, toHexString(data), toHexString([sw1, sw2])))
self.sw1 = sw1; self.sw2 = sw2
errorchain[0](response, sw1, sw2)
......
......@@ -39,11 +39,14 @@
<h1>Prueba de RFID</h1>
<div class="row">
<div class="btn-group">
<button id="btn1" class="btn btn-secondary">Leer UUID!</button>
<button id="btn2" class="btn btn-info">Inicializar +</button>
<button id="btn1" class="btn btn-success">Leer UUID!</button>
<button id="btn2" class="btn btn-warning">Inicializar +</button>
<button id="btn3" class="btn btn-info">Leer datos</button>
<button id="btn4" class="btn btn-info">Escribir!</button>
<button id="btn4" class="btn btn-info">Borrar</button>
<button id="btn4" class="btn btn-primary">Escribir!</button>
<button id="btn5" class="btn btn-danger">Borrar</button>
<button id="btn6" class="btn btn-primary">Valor</button>
<button id="btn7" class="btn btn-info">INC</button>
<button id="btn8" class="btn btn-info">DEC</button>
</div>
</div>
<div class="row">
......@@ -67,238 +70,184 @@
/*
var socket = io();
*/
var empty_image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8Xw8AAoMBgDTD2qgAAAAASUVORK5CYII=";
let DEFAULT_BLOCK = 4;
let DEFAULT_TEST_DATA = "F0 E1 D2 C3 B4 A5 96 87 78 69 5A 4B 3C 2D 1E 0F";
let DEFAULT_ERASE = "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00";
let DEFAULT_TEST_VALUE = 12345;
let DEFAULT_TEST_VALUE_ADR = 0x23;
let DEFAULT_TEST_VALUE_DELTA = 3;
let empty_image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8Xw8AAoMBgDTD2qgAAAAASUVORK5CYII=";
$(function() {
function read_card(){
function spin(){
$("#reader").text('');
$("#atr").text('');
$("#uiid").text('');
$("#mensaje").text('');
$("#spin").show();
$.ajax('https://127.0.0.1:8000/api/read-card', {method:'GET', timeout: 2000 }).done(function(data,st){
$("#spin").hide();
console.log(data,st);
$("#mensaje").removeClass('alert-danger').removeClass('alert-success');
}
function fail(err,st){
$("#spin").hide();
$("#mensaje").removeClass('alert-success').addClass('alert-danger');
console.log("error", err);
console.log("st", st);
if (err.responseJSON){
var data = err.responseJSON;
$("#mensaje").text(data.message);
} else {
$("#mensaje").text("Sin Conexión con el microservicio de tarjetas https://127.0.0.1:8000");
}
}
function parse_data(data, st){
$("#spin").hide();
console.log(data,st);
if (data.UUIDHex){
$("#uiid").text("UUID: " + data.UUIDHex);
$("#reader").text("Lector: " + data.reader);
$("#atr").html("ATR: <a href=\"https://smartcard-atr.apdu.fr/parse?ATR=" + encodeURIComponent(data.ATR) + "\" target=\"_blank\"> " + data.ATR + "</a>");
if (data.ATR_match.length || data.ATR_possible.length){
$("#atr").append("<h5>Tipo de tarjeta</h5>");
data.ATR_match.forEach(function(e,i){
$("#atr").append((i==0?"<strong class=\"alert-success\">":"") + e + (i==0?"</strong>":"") + "<br/>");
if (data.UUIDHex){
$("#uiid").text("UUID: " + data.UUIDHex);
$("#reader").text("Lector: " + data.reader);
$("#atr").html("ATR: <a href=\"https://smartcard-atr.apdu.fr/parse?ATR=" + encodeURIComponent(data.ATR) + "\" target=\"_blank\"> " + data.ATR + "</a>");
if (data.ATR_match.length || data.ATR_possible.length){
$("#atr").append("<h5>Tipo de tarjeta</h5>");
data.ATR_match.forEach(function(e,i){
$("#atr").append((i==0?"<strong class=\"alert-success\">":"") + e + (i==0?"</strong>":"") + "<br/>");
})
if (data.ATR_possible.length){
$("#atr").append("<br/><h5>Otros tipos</h5>");
data.ATR_possible.forEach(function(e,i){
$("#atr").append(e + "<br/>");
})
if (data.ATR_possible.length){
$("#atr").append("<br/><h5>Otros tipos</h5>");
data.ATR_possible.forEach(function(e,i){
$("#atr").append(e + "<br/>");
})
}
}else{
$("#atr").append("<h5 class=\"alert-danger\">Tarjeta desconocida</h5>");
}
$("#mensaje").removeClass('alert-danger').addClass('alert-success');
$("#mensaje").text(data.message);
}else{
$("#mensaje").removeClass('alert-success').addClass('alert-danger');
$("#mensaje").text(data.error || data.message || "Error al recabar respuesta " + data.toString());
}
}).fail(function(err, st){
$("#spin").hide();
$("#mensaje").removeClass('alert-success').addClass('alert-danger');
console.log("error", err);
console.log("st", st);
if (err.responseJSON){
var data = err.responseJSON;
$("#mensaje").text(data.message);
} else {
$("#mensaje").text("Sin Conexión con el microservicio de tarjetas https://127.0.0.1:8000");
$("#atr").append("<h5 class=\"alert-danger\">Tarjeta desconocida</h5>");
}
});
}
function read_card_data(){
$("#reader").text('');
$("#atr").text('');
$("#uiid").text('');
$("#mensaje").text('');
$("#spin").show();
$.ajax('https://127.0.0.1:8000/api/read-card', {method:'GET', data:{block:3}, timeout: 2000 }).done(function(data,st){
$("#spin").hide();
console.log(data,st);
if (data.UUIDHex){
$("#uiid").text("UUID: " + data.UUIDHex);
$("#reader").text("Lector: " + data.reader);
$("#atr").html("ATR: <a href=\"https://smartcard-atr.apdu.fr/parse?ATR=" + encodeURIComponent(data.ATR) + "\" target=\"_blank\"> " + data.ATR + "</a>");
if (data.ATR_match.length || data.ATR_possible.length){
$("#atr").append("<h5>Tipo de tarjeta</h5>");
data.ATR_match.forEach(function(e,i){
$("#atr").append((i==0?"<strong class=\"alert-success\">":"") + e + (i==0?"</strong>":"") + "<br/>");
})
if (data.ATR_possible.length){
$("#atr").append("<br/><h5>Otros tipos</h5>");
data.ATR_possible.forEach(function(e,i){
$("#atr").append(e + "<br/>");
})
}
}else{
$("#atr").append("<h5 class=\"alert-danger\">Tarjeta desconocida</h5>");
}
$("#mensaje").removeClass('alert-danger').addClass('alert-success');
$("#mensaje").removeClass('alert-danger').addClass('alert-success');
if (data.data){
$("#mensaje").text("Block " + data.data.block + " : " + (data.data.isValue ? data.data.value : data.data.string));
$("#mensaje").text("Block " + data.data.block + " : " + (data.data.isValue ? ("V=" + data.data.value + " adr=" + data.data.value_adr) : data.data.string));
}else{
$("#mensaje").removeClass('alert-success').addClass('alert-danger');
if (data.message != "OK")
$("#mensaje").removeClass('alert-success').addClass('alert-danger');
$("#mensaje").text(data.message);
}
}else{
$("#mensaje").removeClass('alert-success').addClass('alert-danger');
$("#mensaje").text(data.error || data.message || "Error al recabar respuesta " + data.toString());
}
}).fail(function(err, st){
$("#spin").hide();
}else{
$("#mensaje").removeClass('alert-success').addClass('alert-danger');
console.log("error", err);
console.log("st", st);
if (err.responseJSON){
var data = err.responseJSON;
$("#mensaje").text(data.message);
} else {
$("#mensaje").text("Sin Conexión con el microservicio de tarjetas https://127.0.0.1:8000");
}
});
$("#mensaje").text(data.error || data.message || "Error al recabar respuesta " + data.toString());
}
}
function init_card(){
function check_uiid(){
if ($("#uiid").text().trim().length == 0){
console.log("sin uuid");
$("#mensaje").removeClass('alert-success').addClass('alert-danger');
$("#mensaje").text("identifique una tarjeta primero");
return;
}else{
console.log("trying uuid", $("#uiid").text().trim())
return null;
}
$("#reader").text('');
$("#atr").text('');
$("#mensaje").text('');
$("#spin").show();
$.ajax('https://127.0.0.1:8000/api/init-card', {method:'POST', data:{uuid:$("#uiid").text().substring(6)}, timeout: 2000 }).done(function(data,st){
$("#spin").hide();
console.log(data,st);
if (data.UUIDHex){
$("#uiid").text("UUID: " + data.UUIDHex);
$("#reader").text("Lector: " + data.reader);
$("#atr").html("ATR: <a href=\"https://smartcard-atr.apdu.fr/parse?ATR=" + encodeURIComponent(data.ATR) + "\" target=\"_blank\"> " + data.ATR + "</a>");
if (data.ATR_possible && data.ATR_possible.length || data.ATR_match && data.ATR_match.length){
$("#atr").append("<h5>Tipo de tarjeta</h5>");
data.ATR_match.forEach(function(e,i){
$("#atr").append((i==0?"<strong class=\"alert-success\">":"") + e + (i==0?"</strong>":"") + "<br/>");
})
if (data.ATR_possible && data.ATR_possible.length){
$("#atr").append("<br/><h5>Otros tipos</h5>");
data.ATR_possible.forEach(function(e,i){
$("#atr").append(e + "<br/>");
})
}
}else{
$("#atr").append("<h5 class=\"alert-danger\">Tarjeta desconocida</h5>");
}
$("#mensaje").removeClass('alert-danger').addClass('alert-success');
$("#mensaje").text(data.message);
}else{
$("#mensaje").removeClass('alert-success').addClass('alert-danger');
$("#mensaje").text(data.error || data.message || "Error al recabar respuesta " + data.toString());
}
}).fail(function(err, st){
$("#spin").hide();
$("#mensaje").removeClass('alert-success').addClass('alert-danger');
console.log("error", err);
console.log("st", st);
if (err.responseJSON){
var data = err.responseJSON;
$("#mensaje").text(data.message);
} else {
$("#mensaje").text("Sin Conexión con el microservicio de tarjetas https://127.0.0.1:8000");
}
});
console.log("trying uuid", $("#uiid").text().trim())
return $("#uiid").text().substring(6);
}
function put_get_huella(metodo){
if (metodo == 'POST'){
var minuta = $("#minuta").val();
$("#dbmp").hide();
$("#dwsq").hide();
$("#dmin").hide();
if (!minuta) { alert("Copie la minuta en base64"); return;}
data = {minuta : minuta};
console.log('data',data);
} else{
$("#minuta").val("");
data = null;
}
//$("#error").text(metodo);
document.getElementById("img").src = empty_image;
$("#quality").text("");
$("#score").text("");
$("#mensaje").text("Coloque su huella...");
$("#spin").show();
$("#img").hide();
$.ajax(
'https://127.0.0.1:3443/v1/huella',
{
method: metodo,
data: data
}
).done(function(data, status){
$("#spin").hide();
console.log(status,data);
if (data.error)
$("#mensaje").removeClass('alert-success').addClass('alert-danger');
else{
$("#mensaje").removeClass('alert-danger').addClass('alert-success');
if (data.huella){
$("#img").show();
document.getElementById("img").src = data.huella.imagen;
$("#dbmp").attr("href", data.huella.imagen);
$("#dbmp").show();
if(data.huella.plantilla){
$("#dwsq").attr("href", "data:application/octet-stream;base64," + data.huella.plantilla);
$("#dwsq").show();
}
if (data.huella.minuta){
document.getElementById("minuta").value = data.huella.minuta;
$("#dmin").attr("href", "data:application/octet-stream," + data.huella.minuta);
$("#dmin").show();
}
}
if (data.quality) $("#quality").text(data.quality + '/40');
if (data.score) $("#score").text('Score: ' + data.score + '/90');
}
$("#mensaje").text(data.mensaje);
}).fail(function(err, st){
$("#spin").hide();
$("#mensaje").removeClass('alert-success').addClass('alert-danger');
console.log("error", err);
console.log("st", st);
if (err.responseJSON){
var data = err.responseJSON;
$("#mensaje").text(data.mensaje);
if (data.quality) $("#quality").text(data.quality + '/40');
if (data.score) $("#score").text('Score: ' + data.score + '/90');
} else {
$("#mensaje").text(err.error().toString());
}
});
function read_card(){
spin();
$.ajax('https://127.0.0.1:8000/api/read-card', {
method: 'GET',
timeout: 2000
}).done(parse_data).fail(fail);
}
function read_card_data(){
spin();
$.ajax('https://127.0.0.1:8000/api/read-card', {
method: 'GET',
data: {block: DEFAULT_BLOCK},
timeout: 2000
}).done(parse_data).fail(fail);
}
function init_card(){
let uiid = check_uiid();
if (!uiid) return;
spin();