Skip to content

Commit

Permalink
version de vot.ar de las PASO 2017 en Salta con datos reales
Browse files Browse the repository at this point in the history
  • Loading branch information
prometheus committed Aug 18, 2017
1 parent ea78af2 commit 932c24f
Show file tree
Hide file tree
Showing 2,041 changed files with 214,784 additions and 2,954 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
tts/

# PyInstaller
# Usually these files are written by a python script from a template
Expand Down
1 change: 0 additions & 1 deletion msa/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
CAM_TOT_VOT = "total_votantes"
PLANILLAS_DATOS_EXTRA = [CAM_TOT_VOT, CAM_BOL_CONT]


try:
from msa.constants_extras import *
except ImportError:
Expand Down
6 changes: 6 additions & 0 deletions msa/core/armve/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ def _inner(self, *args, **kwargs):
pass
return _inner

def arm_event_response(function):
def _inner(self, data, *args, **kwargs):
# la suscripción a eventos no devuelve datos adicionales:
if data:
return function(self, data, *args, **kwargs)
return _inner

def retry_on_error(function):
def _inner(self, *args, **kwargs):
Expand Down
277 changes: 192 additions & 85 deletions msa/core/armve/protocol.py

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions msa/core/armve/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
AUTOFEED_1_MOVE = -128
AUTOFEED_2_MOVE = 8

# Escribe el contenido del acta en dos tags en caso de que no entren
FALLBACK_2K = False
# Rellena todos los bytes que no se escriben en el chip con "\x00" y pisa
# cualquier cosa que hubiera en su lugar
ESCRIBIR_TODOS_BLOQUES = True
Expand Down
14 changes: 13 additions & 1 deletion msa/core/audio/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def __init__(self, as_daemon=True):
self._default_mixer = None
self._queue = []
self.__init_alsa()
self.callback_fin_cola = None

def __init_alsa(self):
try:
Expand Down Expand Up @@ -95,7 +96,7 @@ def run(self):
""" Starts the loop waiting for audio files to be played """
self.__running = True
while self.__running:
if self._queue:
if len(self._queue):
now_filename, now_message = self._queue.pop(0)
if now_message == WavPlayer.PAUSE_TOKEN:
time.sleep(SPEECH_PAUSE)
Expand All @@ -115,6 +116,8 @@ def run(self):
sleep_time = (wav.nframes / wav.frate) - segundos_carga
if sleep_time > 0:
time.sleep(sleep_time)
if not len(self._queue) and self.callback_fin_cola is not None:
self.callback_fin_cola()
# NO SACAR, sino audioplayer se come el 100% de cpu
time.sleep(0.1)

Expand Down Expand Up @@ -174,3 +177,12 @@ def get_volume(self, mixer=None):
except ValueError:
pass
return index

def registrar_callback_fin_cola(self, callback):
"""Registra un callback que será llamado la próxima vez que se vacíe la
cola de mensajes."""
def _inner():
callback()
self.callback_fin_cola = None

self.callback_fin_cola = _inner
4 changes: 3 additions & 1 deletion msa/core/audio/speech.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from threading import Thread

from msa.constants import PATH_TTS
from msa.core.audio.player import WavPlayer
from msa.core.audio.settings import VOLUMEN_GENERAL
from msa.core.data.settings import JUEGO_DE_DATOS
from msa.core.logging import get_logger
Expand All @@ -21,9 +20,11 @@ def __init__(self):
Thread.__init__(self)
global _audio_player
if _audio_player is None or not _audio_player.is_alive():
from msa.core.audio.player import WavPlayer
_audio_player = WavPlayer()
_audio_player.start()
_audio_player.set_volume(VOLUMEN_GENERAL)
self._audio_player = _audio_player
self.reset()
self.setDaemon(True)

Expand All @@ -49,6 +50,7 @@ def decir(self, mensaje, repetir=False):
mensaje -- Mensaje a decir
repite -- Si es True, repite el mensaje (default False)
"""
from msa.core.audio.player import WavPlayer
logger.debug("Diciendo: {}".format(mensaje))
_audio_player.empty_queue()
self.repetir = repetir
Expand Down
5 changes: 3 additions & 2 deletions msa/core/config_manager/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@ def _load_file(self, modulo, file_name):
with open(path, 'r') as file_:
temp_settings = load(file_.read())
settings = {}
for key, value in temp_settings.items():
settings[key] = (value, file_name)
if temp_settings is not None:
for key, value in temp_settings.items():
settings[key] = (value, file_name)

return settings

Expand Down
156 changes: 123 additions & 33 deletions msa/core/crypto/__init__.py
Original file line number Diff line number Diff line change
@@ -1,50 +1,140 @@
from os import urandom
"""Modulo para encriptacion y firma digital de votos y credenciales."""
from binascii import unhexlify

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from construct import Container
from cryptography.hazmat.backends.openssl.backend import Backend
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives.ciphers import Cipher
from cryptography.hazmat.primitives.ciphers.algorithms import AES
from cryptography.hazmat.primitives.ciphers.modes import GCM
from cryptography.hazmat.primitives.hashes import SHA256
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC

from msa.core.crypto.constants import RANDOM_LEN
from msa.core.crypto.constants import DERIVACIONES, PADDING_SERIAL
from msa.core.crypto.settings import ENCRIPTAR_VOTO
from msa.core.crypto.structs import (struct_credencial,
struct_credencial_tecnico, struct_voto)


def encriptar(aes_key, input_, init_vector=None):
if init_vector is None:
init_vector = generate_random_bytes()
cipher = Cipher(algorithms.AES(aes_key), modes.GCM(init_vector),
backend=Backend())
def encriptar(aes_key, init_vector, input_, associated_data=None):
"""Encripta un stream de bytes.
Argumentos:
aes_key -- un stream de 16 bytes con la clave de encriptación.
init_vector -- un stream de 12 bytes con el vector de inicialización.
input_ -- el stream de bytes que queremos encriptar.
associated_data -- la data adicional que queremos usar para encriptar.
"""
# Creamos el cypher
cipher = Cipher(AES(aes_key), GCM(init_vector), backend=Backend())
# Obtenemos el encriptador.
encryptor = cipher.encryptor()
# Si existe agregamos los datos adicionales de autenticación.
if associated_data is not None:
encryptor.authenticate_additional_data(associated_data)
# Encriptamos la informacion.
encrypted = encryptor.update(input_) + encryptor.finalize()
encrypted = init_vector + encryptor.tag + encrypted
return encrypted
# Devolvemos en GCM tag y la data encriptada.
return encryptor.tag, encrypted


def desencriptar(aes_key, input_):
output_ = None
init_vector, tag, seleccion_encriptada = split(input_)
def desencriptar(aes_key, init_vector, gcm_tag, datos_encriptados,
associated_data=None):
"""Encripta un stream de bytes.
cipher = Cipher(algorithms.AES(aes_key), modes.GCM(init_vector, tag),
backend=Backend())
Argumentos:
aes_key -- un stream de 16 bytes con la clave de encriptación.
init_vector -- un stream de 12 bytes con el vector de inicialización.
gcm_tag -- un stream de 16 bytes con el GCM tag
associated_data -- la data adicional que queremos usar para encriptar.
"""
# Creamos el cypher
cipher = Cipher(AES(aes_key), GCM(init_vector, gcm_tag), backend=Backend())
# Obtenemos el desencriptador.
decryptor = cipher.decryptor()
output_ = decryptor.update(seleccion_encriptada) + decryptor.finalize()
# Si existe agregamos los datos adicionales de autenticación.
if associated_data is not None:
decryptor.authenticate_additional_data(associated_data)
# desencriptamos los datos
output_ = decryptor.update(datos_encriptados) + decryptor.finalize()
return output_


def generate_random_bytes(number=RANDOM_LEN):
return urandom(number)
def derivar_clave(clave, salt):
"""Deriva una clave.
Argumentos:
clave -- la clave que queremos derivar.
salt -- el salt que usamos para derivar.
"""
kdf = PBKDF2HMAC(algorithm=SHA256(), length=16, salt=salt,
iterations=DERIVACIONES, backend=Backend())
clave = kdf.derive(clave)
return clave

def split(input_):
return (input_[:RANDOM_LEN], input_[RANDOM_LEN:RANDOM_LEN+16],
input_[RANDOM_LEN+16:])

def derivar_clave(pin, salt):
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=16,
salt=salt,
iterations=1000000,
backend=Backend()
)
clave = kdf.derive(pin)
return clave
def encriptar_voto(aes_key, serial_number, data):
"""Funcion de alto nivel para encriptar un voto.
Argumentos:
aes_key -- un stream de 16 bytes con la clave de encriptación.
serial_number -- un stream de 8 bytes con el serial_number del tag.
data -- el stream de bytes que queremos encriptar.
"""
ret = data
# si no queremos encriptar el voto devolvemos los datos que nos mandaron
if ENCRIPTAR_VOTO:
# El vector tiene que tener 12 bytes asi que le agregamos 4 bytes como
# padding
init_vector = serial_number + PADDING_SERIAL
gcm_tag, data_encriptada = encriptar(aes_key, init_vector, data)
# armamos un container de construct para armar el voto con el formato
# correcto
contenedor = Container(gcm_tag=gcm_tag, len_datos=len(data_encriptada),
datos=data_encriptada)
ret = struct_voto.build(contenedor)

return ret


def desencriptar_voto(aes_key, tag):
"""Funcion de alto nivel para encriptar un voto.
Argumentos:
aes_key -- un stream de 16 bytes con la clave de encriptación.
tag -- un objeto de tipo SoporteDigital que contiene los datos del tag.
"""
ret = tag.datos
# si no estamos encriptando devolvemos los mismos datos que mandaron.
if ENCRIPTAR_VOTO:
# El vector tiene que tener 12 bytes asi que le agregamos 4 bytes como
# padding
init_vector = unhexlify(tag.serial) + PADDING_SERIAL
datos_tag = struct_voto.parse(tag.datos)

ret = desencriptar(aes_key, init_vector, datos_tag.gcm_tag,
datos_tag.datos)
return ret


def desencriptar_credencial(mesa, pin, credencial):
# generamos el vector de inicializacion
init_vector = unhexlify(credencial.serial) + PADDING_SERIAL
# parseamos la credencial con construct
datos = struct_credencial.parse(credencial.datos)
# derivamos la clave
clave = derivar_clave(pin, datos.salt)
# devolvemos la key de la mesa
key = desencriptar(clave, init_vector, datos.gcm_tag, datos.datos, mesa)
return key

def desencriptar_credencial_tecnico(credencial):
# generamos el vector de inicializacion
init_vector = unhexlify(credencial.serial) + PADDING_SERIAL
# parseamos la credencial con construct
datos = struct_credencial_tecnico.parse(credencial.datos)
# derivamos la clave
pin = bytes(credencial.serial, "utf8")
clave = derivar_clave(pin, datos.salt)
# devolvemos la key de la mesa
key = desencriptar(clave, init_vector, datos.gcm_tag, datos.datos)
return key
3 changes: 2 additions & 1 deletion msa/core/crypto/constants.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
RANDOM_LEN = 16
PADDING_SERIAL = b"\x00\x00\x00\x00"
DERIVACIONES = 1000000
2 changes: 1 addition & 1 deletion msa/core/crypto/settings.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ENCRIPTAR_TAG = True
ENCRIPTAR_VOTO = True
28 changes: 28 additions & 0 deletions msa/core/crypto/structs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from construct import Struct, Bytes, UBInt8

# estructura para construir el contenido del tag de un voto.
struct_voto = Struct(
"voto",
Bytes("gcm_tag", 16),
UBInt8("len_datos"),
Bytes("datos", lambda ctx: ctx.len_datos),
)

# estructura para construir el contenido de la credencial de autoridad de mesa.
struct_credencial = Struct(
"credencial",
Bytes("gcm_tag", 16),
Bytes("salt", 16),
Bytes("datos", 16),
Bytes("firma", 48),
)

# estructura para construir el contenido de la credencial de tecnico.
struct_credencial_tecnico = Struct(
"credencial",
Bytes("gcm_tag", 16),
Bytes("salt", 16),
UBInt8("len_datos"),
Bytes("datos", lambda ctx: ctx.len_datos),
Bytes("firma", 48),
)
Loading

0 comments on commit 932c24f

Please sign in to comment.