Bienvenidos a la documentación de SIFVA¶
Descripción General¶
SIFVA pretente ser un cliente para el firmado digital avanzado, la autenticación mediante certificados digitales y la validación de certificados y documentos.
Proporciona soporte para instituciones y personas utilizando:
Para instituciones se utiliza una CA interna de certificados o Dogtag.
Para personas PKCS11 para comunicarse directamente con la tarjeta de firma.
Tantos las personas como las instituciones pueden:
Solicitar una autenticación.
Firmar un documento XML (transacciones), ODF, MS Office, PDF.
Validar un certificado emitido.
Validar un documento XML, ODF, MS Office, PDF.
Clientes disponibles¶
Advertencia
Todos los clientes están en etapa de desarrollo
Personas¶
dfva_client (https://github.com/luisza/dfva_client/) : Cliente en python para interactuar con SIFVA con soporte a PKCS11 para personas.
Instituciones¶
dfva_java (https://github.com/luisza/dfva_java/) : Cliente en java para interactuar con SIFVA para instituciones.
dfva_php (https://github.com/luisza/dfva_php/) : Cliente en php para interactuar con SIFVA para instituciones.
dfva_python (https://github.com/luisza/dfva_python/) : Cliente en python para interactuar con SIFVA para instituciones.
dfva_c (https://github.com/luisza/dfva_c/) : Cliente en c++ para interactuar con SIFVA para instituciones.
dfva_c# (https://github.com/luisza/dfva_csharp/) : Cliente en c# para interactuar con SIFVA para instituciones.
dfva_html (https://github.com/luisza/dfva_html/) : Cliente en javascript/html/css para captar información del usuario y mostrar los códigos provistos por dfva para instituciones.
Conexión con el BCCR (interno)¶
pyfva (https://github.com/solvo/pyfva) : Interactura con el FVA del BCCR, útil en instituciones.
Instalación¶
Nota
Sin hacer, esto solo para quienes estén familiarizados con django y para entorno de desarrollo
Instale las dependencias¶
Clone el repositorio desde
git clone https://github.com/luisza/dfva.git
Instale las dependencias (es recomendable utilizar un entorno virtual)
pip install -r requirements.txt
Modifique el archivo dfva/settings.py según la documentación.
Advertencia
Solo requiere un manejador de CA, puede usar una CA con Python CertBuilder o integrarse con DOGTAG (son excluyentes entre si)
Instalación de una CA dummy¶
Cree la carpeta internal_ca y ejecute el siguiente comando para generar la CA.
python manage.py crea_ca
Se generará los siguientes archivos:
internal_ca/
├── ca_cert.pem
└── ca_key.pem
└── crl.pem
Cambie los permisos de los archivos
cd internal_ca/
chmod 600 ca_cert.pem ca_key.pem crl.pem
En settings.py agregue:
CA_PATH = os.path.join(BASE_DIR, 'internal_ca')
CA_CERT = os.path.join(CA_PATH, 'ca_cert.pem')
CA_KEY = os.path.join(CA_PATH, 'ca_key.pem')
Ejecute la creación de la base de datos.¶
Asegurese de configurar la base de datos, y el motor de base de datos
python manage.py migrate
python manage.py createsuperuser
python manage.py create_admin_institution
Importante create_admin_institution requiere de tener al menos un usuario superadminsitrador.
Corra el programa¶
python manage.py runserver
Corra las tareas syncrónicas¶
Para desarrollo puede no ser necessario corre las tareas asyncrónicas encargadas de notificar a aplicaciones externas.
Si se desea la funcionalidad de notificaciones con tiempo entonces deben ejecutarse en otra pestaña
celery -A dfva worker -l info -B
Settings de interés¶
FVA_HOST = «http://localhost:8001/»: Url donde está corriendo el simulador del FVA BCCR
STUB_SCHEME = “http”: Esquema para el Servicio SOAP del BCCR
STUB_HOST = «localhost:8001»: Máquina del servicio SOAP del BCCR
RECEPTOR_HOST = «http://localhost:8000/»: url base donde se recibirán las notificaciones del FVA BCCR
DEFAULT_BUSSINESS = 1 Identificador del negocio del FVA BCCR
DEFAULT_ENTITY = 1 Identificador de la entidad del FVA BCCR
RECEPTOR_CLIENT = “receptor.client” cliente que recibe las respuestas del FVA BCCR
DFVA_REMOVE_AUTHENTICATION = 5 tiempo en minutos de vida de la autenticación
DFVA_REMOVE_SIGN = 20 tiempo en minutos de vida de la firma
DFVA_PERSON_SESSION = 25 duración en minutos de la sesión de una persona
Instalación de Dogtag manager¶
Se requiere la biblioteca dogtag-pki, y esta a su vez depende de python-nss que tiene como dependencia libnss3-dev por eso ejecutar:
apt-get install libnss3-dev
pip install dogtag-pki
Agregue en settings.py
CAMANAGER_CLASS="corebase.ca_management.dogtag"
DOGTAG_HOST='localhost'
DOGTAG_PORT='8443'
DOGTAG_SCHEME='https'
DOGTAG_AGENT_PEM_CERTIFICATE_PATH=os.path.join(BASE_DIR, 'admin_cert.pem')
DOGTAG_CERTIFICATE_SCHEME={
'O': 'EXAMPLE.COM'
}
DOGTAG_CERT_REQUESTER='dfva'
DOGTAG_CERT_REQUESTER_EMAIL='dfva@example.com'
Nota
Puede instalar una sistema PKI para pruebas utilizando una imágen en docker de la siguiente forma.
Advertencia
Es recomendable correrla en una máquina con más de 2Gb de RAM
Permite activar IPV6
cat /etc/docker/daemon.json
{
"ipv6": true,
"fixed-cidr-v6": "2001:db8:1::/64"
}
docker run --name freeipa-server-container --privileged -ti \
-h ipa.mifirmacr.org \
-v /sys/fs/cgroup:/sys/fs/cgroup:ro \
-p 53:53/udp -p 53:53 \
-p 80:80 -p 443:443 -p 389:389 -p 636:636 -p 88:88 -p 464:464 \
-p 88:88/udp -p 464:464/udp -p 123:123/udp -p 7389:7389 \
-p 8443:8443 -p 8080:8080 -p 9445:9445 \
--security-opt seccomp=unconfined \
--tmpfs /run --tmpfs /tmp \
-v /var/lib/ipa-data:/data:Z freeipa/freeipa-server \
--realm=mifirmacr.org \
--ds-password=LDAPPASSWORD \
--admin-password=ADMINPASSWORD
Se requiere que el usuario sea un agente de Dogtag, de lo contrario no se autenticará, para extraer el certificado pkcs12 del usuario admin que además es un agente dogtag debe buscar la llave en
docker exec -ti <nombre maquina> bash
cat /data/root/ca-agent.p12 | base64
para descomprimir y convertir a pem se recomienda algo como :
echo "codigo base64" | base64 -d > ca-agent.p12
openssl pkcs12 -in ca-agent.p12 -out admin_cert.pem -nodes
La contraseña es la misma que ds-password osea en este caso LDAPPASSWORD
Una vez instalado puede ejecutar
python manage.py runserver
Y acceder a http://localhost:8000 y a partir de ahí iniciar las configuraciones necesarias.
Aspectos de seguridad¶
Comunicación¶
SIFAV es una aplicación RESTFull por lo que usa JSON como modelo de representación de objetos, los objetos son enviados vía POST sobre un canal de comunicación HTTPS. Las peticiones tienen el siguiente formato:
data_hash: Suma hash de datos de tamaño máximo 130 caracteres, usando el algoritmo especificado
algorithm: Algoritmo con que se construye data_hash, debe ser alguno de los siguientes: sha256, sha384, sha512
public_certificate: Certificado de autenticación
data: Datos de solicitud de autenticación encriptados usando AES con la llave de sesión encriptada con PKCS1_OAEP.
encrypt_method: (opcional, por defecto: «aes_eax») Método de encripción del contenido («aes_eax», «aes-256-cfb»)
Además se envía un atributo identificador que depende del tipo de conversación que se quiera entablar, actualmente se pueden comunicar con SIFAV: una institución (institution) con el uuid proporcionado en sifva y una persona (person) con su número de identificación (ver formato).
SIFAV verifica que data_hash sea igual al generado a partir de data utilizando el algoritmo indicado.
Las respuestas tienen el siguiente formato:
data_hash: Suma hash de datos de tamaño máximo 130 caracteres, usando el algoritmo especificado
algorithm: Algoritmo con que se construye data_hash, debe ser alguno de los siguientes: sha256, sha384, sha512 por defecto sha515
data: Datos de respuesta encriptados usando AES Modo EAX con la llave de sesión encriptada con PKCS1_OAEP.
SIFAV intenta desencriptar lo suministrado en data utilizando los juegos de llaves explicados acontinuación:
Institución¶
Para manejar instituciones se debe crear una institución en la plataforma, al crearse se generará una llave privada, una llave pública y un certificado.
La llave privada corresponde a la llave privada de la institución y será utilizada para desencriptar las respuestas de dfva,
La llave pública corresponde a la llave pública de SIFAV que se utilizará para encriptar la información que se envía en data.
En SIFAV se construye dos pares de llaves por cada institución.
Llaves de la aplicación: La llave privada se entrega y la llave pública se guarda y nunca es revelada.
Llaves del servicio: La llave privada se guarda y nunca es revelada y la llave pública se entrega a la institución.
Los juegos de llaves encriptados y el certificado se guardan en la base de datos, excepto la llave privada de la institución, la cual nunca es almacenada en la báse de datos y solo se muestra una vez al usuario. Debido a que tanto las llaves privadas y las públicas son exclusivas de cada institución y generadas dentro de SIFAV la llave pública de la institución nunca es expuesta asegurando aún más la comunicación RSA.
Nota
Se utiliza el SECRET_KEY de Django para generar una llave de encripción para los atributos almacenados en la base de datos, por lo que asegurece cambiar el valor por defecto.
Persona¶
Para la comunicación con personas se utiliza la encripción provista por los dispositivos PKCS11, de ahí se extrae:
Un certificado de Autenticación.
Un certificado de Firma.
En mis pruebas el certificado de firma tiene una llave privada que no permite desencriptar, por lo que solo se utiliza autenticación para comunicación.
Cuando una persona desea comunicarse con SIFAV lo primero que reliza el programa es negociar el token de autenticación, el token es encriptado utilizando la llave pública del certificado de Autenticación en SIFAV y enviado a la aplicación, dicho token solo puede ser desencriptado con el dispositivo PKCS11 y la llave privada de auteticación.
El token será utilizado como token de sesión en el algoritmo AES Modo EAX al encriptar data y deberá ser enviado firmado utilizando alguna de las llaves privadas del dispositivo (según contexto) y se comprobará en SIFAV que el token sea correcto antes de proceder a desencriptar la información.
Almacenamiento¶
Nota
FALTA, Actualemente se guarda la información de verificación en forma plana en una base de datos y nunca se borra, autenticación y firma ya mueve a logs la información.
Advertencia
FALTA, Manejo información sobre los modelos de personas, la información descrita corresponde únicamente a institutiones.
SIFAV se basa en Django por lo que soporta todas las bases de datos que este framework soporta, pero recomendamos Postgresql 9.4 o superior.
Las solicitudes de autenticación tiene un tiempo de vida de al menos 5 minutos (configurables), así una solicitud de autenticación se guardará en la base de datos por el tiempo definido, luego se extrae y se guarda en un archivo de log especiamente diseñado para guardar las solicitudes.
Las solicitudes de firma tienen un tiempo de vida de al menos 20 minutos (configurables), así una solicitud de firma se guardará por el tiempo definido y luego se guardará en un archivo de logs diseñado para guardar estas solicitudes. No se guarda el documento firmado, solo el registro de que se firmó y su suma hash.
Se pretende que las verificaciones de documentos y certificados y las revisiones de suscriptor conectado no se guarden en la base de datos (FALTA).
SIFAV trabaja con tareas asincrónicas llamadas cada 5 y 20 minutos las cuales se encargan de revisar cuales peticiones han vencido el plazo y deben enviarse a logs, debido a este comportamiento algunas peticiones tendrán una duración entre 5-9 minutos para autenticación y 20 a 39 minutos para firma antes de ser enviadas a logs. Debido a que se provee la opción de solicitar la información de una petición para clientes no web esta información debe permanecer por un periodo de tiempo, además los mecanismos de control propios impedirá que una petición cuyo tiempo de vida haya caducado pueda ser obtenida por un cliente.
Bitácoras¶
SIFAV usa al máximo el sistema de bitácoras de Django por lo que es ampliamente configurable. Actualmente genera los siguientes logs:
pyfva (debug, info, errors): Bitácoras de comunicación con BCCR FVA
dfva (debug, info, errors): Bitácoras de funcionamiento interno de SIFAV.
dfva_authentication (info): Bitácora de solicitudes de autenticación
dfva_sign (info): Bitácora de solicitudes de firma.
Las bitácoras dfva_authentication, dfva_sign guardan los objecto en formato json. Actualmente la mayoría de los datos guardados son volcados a estas bitácoras.
Transporte¶
Se recomienda implementar HTTP Strict Transport Security (HSTS) en el sistemas en producción.
Disponibilidad¶
SIFAV está basado en Django y utiliza todos los mecanismos provistos por este, así también posee todas las bondades en cuanto a escalabilidad. Por ello SIFAV es escalable tanto Horizontal como Verticalmente.
Aunque AES EAX no es thread safe, solo se utiliza un hilo por encripción y abonando el hecho que Django es thread safe, se concidera que SIFAV posee la capacidad de ejecutarse en entornos multi-hilo, con un pequeño impacto en los tiempos de encripción.
Nota
Más pruebas del comportamiento multihilo son recomendables.
Manejo de los certificados¶
SIFAV es versatil y permite configurar el manejador de certificados, con ello permite comunicarse con la infraestructura de PKI que se desee.
Actualmente, se soporta la integración con Dogtag y también se soporta CA’s creadas con Python Certbuilder para desarrollo utilizando el manejador CA simple
CA Simple¶
Advertencia
No utilizar en producción, este sistema está desarrollado para trabajar en desarrollo sin la necesidad de una infraestructura compleja.
SIFAV trae un manejador y constructor de Autoridades de Certificados (CA), y debe construirse después de la instalación usando el comando:
python manage.py crea_ca
Los de certificados, se generan en el directorio
internal_ca/
├── ca_cert.pem
└── ca_key.pem
└── crl.pem
Asegurar dichos archivos escapa al alcance de este documento, pero siempre es útil asegurar que solo el usuario tiene permiso para acceder a ellos.
chmod 600 ca_cert.pem ca_key.pem crl.pem
DogTag¶
Nota
Para la instalación ver la sección de instalación de SIFAV.
Dogtag es una aplicación que se integra con FreeIPA para proporcionar una robusta infraestructura PKI, actualmente el cliente desarrollado se integra con el API rest de Dogtag para generar, validar y revocar certificados.
Una aspecto importante de la implementación es que requiere que el usuario utilizado sea un agente de Dogtag capaz de solicitar y aprovar certificados, por lo que la aplicación será capaz de generar certificados en Dogtag de forma automática, debe contemparse esta situación dentro de la política de la PKI.
Dentro del proceso de solicitud de certificados se genera un objeto X509Request (certificate signing request csr) utilizando el esquema proporcionado en DOGTAG_CERTIFICATE_SCHEME exceptuando los campos OU y CN que corresponden a:
OU = institution unit
CN = domain
Ambos recolectados desde la interfaz.
En la validación del certificado se utiliza el serial_number del certificado para solicitar el estado del mismo en Dogtag. Además se valida el issuer sea identico al issuer de la instalación de Dogtag, así se garantiza que dicho certificado fue emitido por el issuer y que el serial_number es el adecuado.
Encripción¶
Se recomienda utilizar transporte https para la puesta en producción de esta plataforma, aún así SIFAV posee una segunda capa de encripción, utilizando los algoritmos.
AES EAX: Algoritmo simetrico, utilizado para encriptar el contenido, posee un token de sessión y un atributo IV (nonce), así como un Tag parameter. Este par debe ser único en cada encripción, osea no se puede repetir el IV con el mismo token de sessión. Actualmente tanto el token de sessión, el Tag parameter y el IV son de 16 bytes.
AES 256 CBF: Algoritmo simetrico, utilizado para encriptar el contenido, posee un token de sessión y un atributo IV (nonce). Este par debe ser único en cada encripción, osea no se puede repetir el IV con el mismo token de sessión. Actualmente tanto el token de sessión es de 32 bytes y el IV son de 16 bytes. (usar solamente si EAX no está disponible en el lenguaje).
PKCS1 OAEP: Algoritmo de encripción asimétrico, es utilizado para encriptar el token de sessión. También conocido como RSA/NONE/OAEPWithSHA1AndMGF1Padding en ambiente java.
Estructura de la encripción es: Token encriptado + IV (nonce) + datos encriptados.
Advertencia
en algunas implementaciones como en java se incluye dentro de los datos encriptados el IV al final, por lo que debe removerse y ponerse después del token encriptado.
API de Comunicación¶
SIFVA es una aplicación RESTFull por lo que usa JSON como modelo de representación de objetos, los objetos son enviados vía POST sobre un canal de comunicación HTTPS. Las peticiones tienen el siguiente formato:
data_hash: Suma hash de datos de tamaño máximo 130 caracteres, usando el algoritmo especificado
algorithm: Algoritmo con que se construye data_hash, debe ser alguno de los siguientes: sha256, sha384, sha512
public_certificate: Certificado de autenticación
data: Datos de solicitud de autenticación encriptados usando AES con la llave de sesión encriptada con PKCS1_OAEP.
encrypt_method: (opcional, por defecto: «aes_eax») Método de encripción del contenido («aes_eax», «aes-256-cfb»)
Además se envía un atributo identificador que depende del tipo de conversación que se quiera entablar, actualmente se pueden comunicar con SIFVA: una institución (institution) con el uuid proporcionado en dfva y una persona (person) con su número de identificación (ver formato).
SIFVA verifica que data_hash sea igual al generado a partir de data utilizando el algoritmo indicado.
Las respuestas tienen el siguiente formato:
data_hash: Suma hash de datos de tamaño máximo 130 caracteres, usando el algoritmo especificado
algorithm: Algoritmo con que se construye data_hash, debe ser alguno de los siguientes: sha256, sha384, sha512 por defecto sha515
data: Datos de respuesta encriptados usando AES Modo EAX con la llave de sesión encriptada con PKCS1_OAEP.
Instituciones¶
Autenticación¶
- AuthenticateRequestViewSet.institution(request, *args, **kwargs)[fuente]¶
POST /authenticate/institution/
Solicita una petición de autenticación para un usuario
Los valores a suministrar en el parámetro data son:
institution: uid de la institucion ver code en detalles de institución,
notification_url: URL para la notificación (debe estar inscrita) o N/D si marca falso en not_webapp,
identification: Identificación de la persona a autenticar,
request_datetime: Hora de petición en formato “%Y-%m-%d %H:%M:%S”, osea “2006-10-25 14:30:59”
encrypt_method: (opcional, default: «aes_eax») Método de encripción de segunda fase. («aes_eax», «aes-256-cfb»)
Data es un diccionario, osea un objeto de tipo clave -> valor
Los valores devueltos son:
expiration_datetime: hora final de validez
request_datetime: Hora de recepción de la solicitud
id_transaction: Id de trasnacción en el FVA del BCCR
status: Código de error de la transacción
status_text Descripción para humanos del código de error
identification: Identificador del suscriptor
code: Código para mostrar al usuario
received_notification: True si la autenticación ha sido procesada, False si está esperando al usuario
resume: Resumen de la transacción.
hash_docsigned: Normalmente Null, Base64 hash del documento firmado si el documento existe
hash_id_docsigned: 0- no se ha firmado 1- Sha256, 2- Sha384, 3- Sha512
- AuthenticateRequestViewSet.institution_show(request, *args, **kwargs)[fuente]¶
POST /authenticate/{id_transaction}/institution_show/
Solicita el estado de una petición de autenticación para un usuario
Los valores a suministrar en el parámetro data son:
institution: uid de la institucion ver code en detalles de institución,
notification_url: URL para la notificación (debe estar inscrita) o N/D si marca falso en not_webapp,
request_datetime: Hora de petición en formato “%Y-%m-%d %H:%M:%S”, osea “2006-10-25 14:30:59”
Data es un diccionario, osea un objeto de tipo clave -> valor
id_transaction Corresponde al id de la trasnacción del BCCR
Los valores devueltos son:
expiration_datetime: hora final de validez
request_datetime: Hora de recepción de la solicitud
id_transaction: Id de trasnacción en el FVA del BCCR
status: Código de error de la transacción
status_text Descripción para humanos del código de error
identification: Identificador del suscriptor
code: Código para mostrar al usuario
received_notification True si la autenticación ha sido procesada, False si está esperando al usuario
resume: Resumen de la transacción.
hash_docsigned: Base64 hash del documento firmado si el documento existe
hash_id_docsigned: 0- no se ha firmado 1- Sha256, 2- Sha384, 3- Sha512
- AuthenticateRequestViewSet.institution_delete(request, *args, **kwargs)[fuente]¶
POST /authenticate/{id_transaction}/institution_delete/
Elimina una petición de autenticación para un usuario
Los valores a suministrar en el parámetro data son:
institution: uid de la institucion ver code en detalles de institución,
notification_url: URL para la notificación (debe estar inscrita) o N/D si marca falso en not_webapp,
request_datetime: Hora de petición en formato “%Y-%m-%d %H:%M:%S”, osea “2006-10-25 14:30:59”
Data es un diccionario, osea un objeto de tipo clave -> valor
id_transaction Corresponde al id de la trasnacción del BCCR
Los valores devueltos son:
result True/False si se eliminó la petición o no
Firma¶
- SignRequestViewSet.institution(request, *args, **kwargs)[fuente]¶
POST /sign/institution/
Solicita una firma de un documento xml, odf o msoffice para un usuario
Los valores a suministrar en el parámetro data son:
institution: uid de la institucion ver code en detalles de institución,
notification_url: URL para la notificación (debe estar inscrita) o N/D si marca falso en not_webapp,
document: Archivo en base64,
format: tipo de archivo (xml_cofirma, xml_contrafirma, odf, msoffice, pdf),
algorithm_hash: algoritmo usado para calcular hash,
document_hash: hash del documento,
resumen: Información de ayuda acerca del documento,
identification: Identificación de la persona a autenticar,
request_datetime: Hora de petición en formato “%Y-%m-%d %H:%M:%S”, osea “2006-10-25 14:30:59”
reason: Razón de firma PDF (obligatorio solo en PDF)
place: Lugar de firma en PDF (obligatorio solo en PDF)
Data es un diccionario, osea un objeto de tipo clave -> valor
Los valores devueltos son:
expiration_datetime: hora final de validez
request_datetime: Hora de recepción de la solicitud
id_transaction: Id de trasnacción en el FVA del BCCR
signed_document: Normalmente None, es un campo para almacenar el documento, pero no se garantiza que venga el documento firmado
status: Código de error de la transacción
status_text Descripción para humanos del código de error
identification: Identificador del suscriptor
code: Código para mostrar al usuario
received_notification True si la autenticación ha sido procesada, False si está esperando al usuario
resume: Resumen de la transacción.
hash_docsigned: Normalmente Null, Base64 hash del documento firmado si el documento existe
hash_id_docsigned: 0- no se ha firmado 1- Sha256, 2- Sha384, 3- Sha512
- SignRequestViewSet.institution_show(request, *args, **kwargs)[fuente]¶
POST /sign/{id_transaction}/institution_show/
Verifica la firma dado un código y si respectiva identificación
Los valores a suministrar en el parámetro data son:
institution: uid de la institucion ver code en detalles de institución,
notification_url: URL para la notificación (debe estar inscrita) o N/D si marca falso en not_webapp,
identification: Identificación de la persona a autenticar,
request_datetime: Hora de petición en formato “%Y-%m-%d %H:%M:%S”, osea “2006-10-25 14:30:59”
Data es un diccionario, osea un objeto de tipo clave -> valor
id_transaction Corresponde al id de la trasnacción del BCCR
Los valores devueltos son:
expiration_datetime: hora final de validez
request_datetime: Hora de recepción de la solicitud
id_transaction: Id de trasnacción en el FVA del BCCR
signed_document: Normalmente None, es un campo para almacenar el documento, pero no se garantiza que venga el documento firmado
status: Código de error de la transacción
status_text Descripción para humanos del código de error
identification: Identificador del suscriptor
code: Código para mostrar al usuario
received_notification True si la autenticación ha sido procesada, False si está esperando al usuario
resume: Resumen de la transacción.
hash_docsigned: Normalmente Null, Base64 hash del documento firmado si el documento existe
hash_id_docsigned: 0- no se ha firmado 1- Sha256, 2- Sha384, 3- Sha512
- SignRequestViewSet.institution_delete(request, *args, **kwargs)[fuente]¶
POST /sign/{id_transaction}/institution_delete/
Elimina una petición de firma dado un código de transacción del BCCR
Los valores a suministrar en el parámetro data son:
institution: uid de la institucion ver code en detalles de institución,
notification_url: URL para la notificación (debe estar inscrita) o N/D si marca falso en not_webapp,
request_datetime: Hora de petición en formato “%Y-%m-%d %H:%M:%S”, osea “2006-10-25 14:30:59”
Data es un diccionario, osea un objeto de tipo clave -> valor
id_transaction Corresponde al id de la trasacción del BCCR
Los valores devueltos son:
result True/False si se eliminó la petición o no
Validación¶
- ValidateInstitutionViewSet.institution_certificate(request, *args, **kwargs)[fuente]¶
POST /validate/institution_certificate/
Solicita una de un certificado de autenticación para un usuario
Los valores a suministrar en el parámetro data son:
institution: uid de la institucion ver code en detalles de institución,
notification_url: URL para la notificación (debe estar inscrita) o N/D si marca falso en not_webapp,
document: Archivo en base64 del certificado,
request_datetime: Hora de petición en formato “%Y-%m-%d %H:%M:%S”, osea “2006-10-25 14:30:59”
Data es un diccionario, osea un objeto de tipo clave -> valor
Los valores devueltos son:
identification: Identificación del suscriptor
request_datetime: Hora de recepción de la solicitud
code: Código de identificación de la transacción (no es el mismo que el que se muestra en al usuario en firma)
status: Estado de la solicitud
status_text: Descripción en texto del estado
full_name: Nombre completo del suscriptor
start_validity: Inicio de la vigencia del certificado
end_validity: Fin de la vigencia del certificado
was_successfully: Si la verificación del certificado fue exitosa
Nota: Si la validación del certificado no fue exitosa, entonces los campos de identificación, full_name, start_validity, end_validity deben ignorase o son nulos.
- ValidateInstitutionViewSet.institution_document(request, *args, **kwargs)[fuente]¶
POST /validate/institution_document/
Solicita una verificación de firma de un documento xml
Los valores a suministrar en el parámetro data son:
institution: uid de la institucion ver code en detalles de institución,
notification_url: URL para la notificación (debe estar inscrita) o N/D si marca falso en not_webapp,
document: Archivo en base64 del certificado,
format: Formato de documento a validar disponibles (cofirma, contrafirma, msoffice, odf)
request_datetime: Hora de petición en formato “%Y-%m-%d %H:%M:%S”, osea “2006-10-25 14:30:59”
Data es un diccionario, osea un objeto de tipo clave -> valor
Los valores devueltos son:
identification: Identificación del suscriptor
request_datetime: Hora de recepción de la solicitud
code: Código de identificación de la transacción (no es el mismo que el que se muestra en al usuario en firma)
status: Estado de la solicitud
status_text: Descripción en texto del estado
was_successfully: Si la verificación del certificado fue exitosa
warnings: Lista de advertencias
errors: Lista de errores encontrados en el documento del tipo [ {“code”: “codigo”,”description”: “descripción”}, … ]
- signers: Lista con la información de los firmantes
[ {“identification_number”: “08-8888-8888”, “full_name”: “nombre del suscriptor”, “signature_date”: timezone.now()}, … ]
Nota: Si la validación del documento no fue exitosa, entonces los campos de firmantes deben ignorase o son nulos.
- ValidateSubscriptorInstitutionViewSet.institution_suscriptor_connected(request, *args, **kwargs)[fuente]¶
POST /validate/institution_suscriptor_connected/
Verifica si una persona está conectada (es contactable por el BCCR).
Los valores a suministrar en el parámetro data son:
institution: uid de la institucion ver code en detalles de institución,
notification_url: URL para la notificación (debe estar inscrita) o N/D si marca falso en not_webapp,
identification: Identificación de la persona a buscar,
request_datetime: Hora de petición en formato “%Y-%m-%d %H:%M:%S”, osea “2006-10-25 14:30:59”
Data es un diccionario, osea un objeto de tipo clave -> valor
- Retorna:
is_connected: True si la persona está conectada, false si no lo está
Personas¶
Autenticación¶
- class person.authenticator.views.AuthenticatePersonView(**kwargs)[fuente]¶
Solucitud de autenticación de una persona
POST /person/authenticate/
Solicita una petición de autenticación para un usuario
Los valores a suministrar en el parámetro data son:
person: identificación de la persona solicitante de autenticación,
identification: Identificación de la persona a autenticar,
request_datetime: Hora de petición en formato “%Y-%m-%d %H:%M:%S”, osea “2006-10-25 14:30:59”
Data es un diccionario, osea un objeto de tipo clave -> valor
Los valores devueltos son:
expiration_datetime: hora final de validez
request_datetime: Hora de recepción de la solicitud
id_transaction: Id de trasnacción en el FVA del BCCR
status: Código de error de la transacción
identification: Identificador del suscriptor
code: Código para mostrar al usuario
received_notification True si la autenticación ha sido procesada, False si está esperando al usuario
signed_document Siempre es None puesto que el documento todavía no se ha firmado a este punto
duration Tiempo en segundos que dura la transacción
Solucitud de información de una transacción de autenticación
GET /person/authenticate/{transaction_id}/
Solicita un estado de la solicitud de autenticación para un usuario
Los valores a suministrar en el parámetro data son:
transaction_id: identificación de la transacción de autenticación de la que se requiere información
Data es un diccionario, osea un objeto de tipo clave -> valor
Los valores devueltos son:
expiration_datetime: hora final de validez
request_datetime: Hora de recepción de la solicitud
id_transaction: Id de trasnacción en el FVA del BCCR
status: Código de error de la transacción
identification: Identificador del suscriptor
code: Código para mostrar al usuario
received_notification True si la autenticación ha sido procesada, False si está esperando al usuario
signed_document Documento firmado en base64 o None si aún no se ha firmado la autenticación
duration Tiempo en segundos que dura la transacción
Elimina la información de la transacción de autenticación
DELETE /person/authenticate/{transaction_id}/
Los valores devueltos son:
No tiene valores devueltos
Firma¶
- class person.signer.views.SignPersonView(**kwargs)[fuente]¶
Solucitud de Firma de documentos de una persona
POST /sign/person/
Solicita una firma de un documento xml, odf o msoffice para un usuario
Los valores a suministrar en el parámetro data son:
person: identificación de la persona solicitante de firma,
notification_url: URL para la notificación (debe estar inscrita) o N/D si marca falso en not_webapp,
document: Archivo en base64,
format: tipo de archivo (xml_cofirma,xml_contrafirma, odf, msoffice),
algorithm_hash: algoritmo usado para calcular hash,
document_hash: hash del documento,
resumen: Información de ayuda acerca del documento,
identification: Identificación de la persona a firmar,
request_datetime: Hora de petición en formato “%Y-%m-%d %H:%M:%S”, osea “2006-10-25 14:30:59”
Data es un diccionario, osea un objeto de tipo clave -> valor
Los valores devueltos son:
expiration_datetime: hora final de validez
request_datetime: Hora de recepción de la solicitud
id_transaction: Id de trasnacción en el FVA del BCCR
signed_document: Normalmente None, es un campo para almacenar el documento, pero no se garantiza que venga el documento firmado
status: Código de error de la transacción
identification: Identificador del suscriptor
code: Código para mostrar al usuario
received_notification True si la autenticación ha sido procesada, False si está esperando al usuario
duration Tiempo en segundos que dura la transacción
Solucitud de información de una transacción de firmado
GET /person/sign/{transaction_id}/
Verifica la firma dado un código y su respectiva identificación
Los valores a suministrar en el parámetro data son:
person: identificación de la persona solicitante de firma,
identification: Identificación de la persona a autenticar,
request_datetime: Hora de petición en formato “%Y-%m-%d %H:%M:%S”, osea “2006-10-25 14:30:59”
Data es un diccionario, osea un objeto de tipo clave -> valor
Los valores devueltos son:
expiration_datetime: hora final de validez
request_datetime: Hora de recepción de la solicitud
id_transaction: Id de trasnacción en el FVA del BCCR
status: Código de error de la transacción
identification: Identificador del suscriptor
code: Código para mostrar al usuario
received_notification True si la autenticación ha sido procesada, False si está esperando al usuario
signed_document Documento firmado en base64 o None si aún no se ha firmado la autenticación
duration Tiempo en segundos que dura la transacción
Elimina la información de la transacción de firma
DELETE /person/authenticate/{transaction_id}/
Los valores devueltos son:
No tiene valores devueltos
Validación¶
- class person.validator.views.ValidateCertificatePersonViewSet(**kwargs)[fuente]¶
Valida si un certificado de la jerarquía nacional es válido.
POST /person/validate_certificate
Solicita una de un certificado de autenticación para un usuario
Los valores a suministrar en el parámetro data son:
person: Identificación de la persona validante,
document: Archivo en base64 del certificado,
request_datetime: Hora de petición en formato “%Y-%m-%d %H:%M:%S”, osea “2006-10-25 14:30:59”
format Debe ser siempre «certificate»
Data es un diccionario, osea un objeto de tipo clave -> valor
Los valores devueltos son:
identification: Identificación del suscriptor
request_datetime: Hora de recepción de la solicitud
code: Código de identificación de la transacción (no es el mismo que el que se muestra en al usuario en firma)
status: Estado de la solicitud
codigo_de_error: Códigos de error del certificado, si existen
full_name: Nombre completo del suscriptor
start_validity: Inicio de la vigencia del certificado
end_validity: Fin de la vigencia del certificado
was_successfully: Si la verificación del certificado fue exitosa
Nota: Si la validación del certificado no fue exitosa, entonces los campos de identificación, nombre_completo, inicio_vigencia, fin_vigencia deben ignorase o son nulos.
- class person.validator.views.ValidateDocumentPersonViewSet(**kwargs)[fuente]¶
Solicita una verificación de firma de un documento
POST /person/validate_document/
Los valores a suministrar en el parámetro data son:
person: Identificación de la persona validante,
document: Archivo en base64 del certificado,
format: Formato del documento a validar disponibles (cofirma, contrafirma, msoffice, odf)
request_datetime: Hora de petición en formato “%Y-%m-%d %H:%M:%S”, osea “2006-10-25 14:30:59”
Data es un diccionario, osea un objeto de tipo clave -> valor
Los valores devueltos son:
identification: Identificación del suscriptor
request_datetime: Hora de recepción de la solicitud
code: Código de identificación de la transacción (no es el mismo que el que se muestra en al usuario en firma)
status: Estado de la solicitud
status_text: Descripción en texto del estado
was_successfully: Si la verificación del certificado fue exitosa
validation_data Contiene la información de la validación en un diccionario con los siguientes campos
firmas: Lista de firmas presentes en el documento, una firma de ejemplo podría ser algo así
{'es_valida': True, 'es_avanzada': True, 'error': False, 'detalle_de_error': '', 'garantia_de_integridad_y_autenticidad': True, 'garantia_de_validez_tiempo': [0, 'Tiene Garantía'], 'detalle': {'integridad': {'estado': False, 'se_evalua': True, 'respuesta': 'ok', 'codigo': 1}, 'jerarquia_de_confianza': {'estado': 0, 'se_evalua': True, 'respuesta': 'ok', 'codigo': 1}, 'vigencia': {'estado': False, 'se_evalua': True, 'respuesta': 'ok', 'codigo': 1}, 'tipo_de_certificado': {'estado': 0, 'se_evalua': True, 'respuesta': 'ok', 'codigo': 1}, 'revocacion': {'estado': 0, 'se_evalua': True, 'respuesta': 'ok', 'codigo': 1}, 'fecha_de_firma': {'estado': False, 'se_evalua': True, 'respuesta': 'ok', 'codigo': 1, 'fecha_de_estama': '2021-05-20T00:00:00Z'}}, 'autoria_del_firmante': {'nombre': 'Joan Lucas Arce', 'identificacion': '0408880888', 'tiene_autoria': True}}
resumen: Resumen de las firmas (una versión con menos campos de las firmas)
{'firmante': 'Luis Madrigal Viquez', 'identificacion': '0208880888', 'garantia_de_integridad_y_autenticidad': True, 'garantia_validez_en_el_tiempo': True, 'resultado': 0, 'fecha_estampa_de_tiempo': '2021-05-20T23:30:16Z', 'tipo_identificacion': 0, 'tiene_fecha_estampa_de_tiempo': True}
errores: Cadena de texto con mensajes de error presentes en las firmas del documento
- class person.validator.views.ValidateSubscriptorPersonViewSet(**kwargs)[fuente]¶
Verifica si una persona está conectada (es contactable por el BCCR).
POST /person/validate_suscriptor/
Los valores a suministrar en el parámetro data son:
person: Identificación de la persona validante,
identification: Identificación de la persona a buscar,
request_datetime: Hora de petición en formato “%Y-%m-%d %H:%M:%S”, osea “2006-10-25 14:30:59”
Data es un diccionario, osea un objeto de tipo clave -> valor
- Retorna:
is_connected: True si la persona está conectada, false si no lo está
Login¶
- PersonLoginView.list(request, *args, **kwargs)[fuente]¶
Gestiona la operación de verdad, para la generación de token a firmar. En el flujo se solicita a esta vista 2 operadores y una función de operación, luego el cliente calcula el resultado y lo envía firmado a la vísta vía POST, SIFVA valida el resultado y lo compara con lo enviado, si ambos son iguales entonces autentica al usuario.
GET /login/
Parámetros GET
serial: Serial de la tarjeta con la cual autenticarse.
person: Identificación de la persona
Response:
transaction_id: ID del objeto de autenticación.
operatorA: Operadorador izquierdo
operand: Operadorador
operatorB: Operadorador derecho
- PersonLoginView.create(request, *args, **kwargs)[fuente]¶
Autentica el usuario usando una prueba de verdad.
POST /login/
Permite a una persona autenticarse en DFVA, un token de sección es retornado y deberá ser usuado para encriptar la comunicación.
Los valores a suministrar son:
data_hash: Suma hash de datos de tamaño máximo 130 caracteres, usando el algoritmo especificado
algorithm: Algoritmo con que se construye data_hash, debe ser alguno de los siguientes: sha256, sha384, sha512
public_certificate: Certificado de autenticación del dispositivo pkcs11
person: Identificación de la persona,
code: Identificación de la persona firmada con la llave privada del certificado de autenticación.
transaction_id: Id de transacción usado para determinar la operación.
Los valores devueltos son:
identification: Identificación del suscriptor
token: Token de sección para encriptar atributo data posteriormente
expiration_datetime_token: Hora máxima para usar el token
last_error_code: Código de estado de la transacción
error_text: Descripción de los errores encontrados
Notififcación para Instituciones¶
- receptor.notify.send_notification(data, serializer=None, request=None, encrypt_method='aes_eax')[fuente]¶
Envia notificación a la institución, cuando se recibe una respuesta por parte del BCCR, este método reenvía la respuesta a la URL especificada en la petición.
La estructura de envío es:
- Params id_transaction
Id de transacción del BCCR
- Params data
Es un diccionario con los siguientes atributos
code: Código de identificación de la transacción (no es el mismo que el que se muestra en al usuario en firma)
identification: Identificador del suscriptor
id_transaction: Id de trasnacción en el FVA del BCCR
request_datetime: Hora de recepción de la solicitud
signed_document: Almacena el documento, pero no se garantiza que venga el documento firmado, puede ser None
expiration_datetime: Hora de recepción de la solicitud
received_notification: True si la autenticación ha sido procesada, False si está esperando al usuario
duration: tiempo que duró entre que fue enviada y fue recibida
status: Código de error de la transacción
status_text: Descripción en texto del estado
- Params hashsum
Suma hash realizada a data
- Params algorithm
Algoritmo con el que se realizó la suma hash
Por defecto se utiliza el método de encripción seleccionado al realizar la petición por parte de la institución, pero en caso de no lograrse identificar el método se utiliza por defecto “aes_eax”
Flujos de interacción¶
Instituciones¶
Flujo de Autenticación¶

El usuario ingresa a la plataforma de la institución y se le despliega un modal donde se le pide la identificación
La identificación se envía a la plataforma de la institución
La aplicación mediante alguna de las bibliotecas de comunicación con dfva envía la petición utilizando un canal https vía JSON y encritpta en el atributo data la información, usando AES EAX + PKCS1_OEAP.
Dentro de SIFVA se verifica que:
La institución está registrada y activa
La URL de notificación está registrada o la aplicación fue inscrita sin URL de notificación (para aplicaciones no web).
El certificado está vigente y es válido.
Los datos pueden ser desencriptados usando la llave privada de SIFVA asignada a la aplicación.
La suma de verificación de los datos son iguales.
En caso de que alguna de estas verificaciones falle SIFVA devolverá un error.
La petición es almacenada en la base de datos y enviada mediante PyFVA al servicio de FVA del BCCR utilizando un canal SINPE.
Cuando se recibe la respuesta del FVA el código se guarda en la base de datos actualizando la información de la petición.
La respuesta se envía a la institución mediante el mismo canal usando JSON y encriptando el atributo data con AES EAX + PKCS1_OEAP. Se utiliza la llave pública de la aplicación para encriptar la comunicación (nunca publicada).
El código de identificación se le muestra al usuario y el usuario mediante el cliente de firma del BCCR firma la petición de autenticación.
El FVA del BCCR notifica a SIFVA que el usuario ha firmado la autenticación, una vez que llega a SIFVA se almacena en la base de datos.
Si la aplicación provee una URL de notificación se envía la notificación usando JSON y encriptando el atributo data con AES EAX + PKCS1_OEAP. Se utiliza la llave pública de la aplicación para encriptar la comunicación (nunca publicada).
Una vez la aplicación de la institución es notificada se autentica al usuario y se redirecciona al usuario a una vista autenticada.
Mientras tanto periódicamente se eliminan los datos de las peticiones vencidas guardando dentro de un archivo de log las peticiones eliminadas.
Flujo de estado de petición de Autenticación¶

El proceso de verificación inicia a partir del paso 11 del flujo de autenticación, osea a partir de la llegada del token a la aplicación de la institución.
La aplicación de la institución solicita el estado de la solicitud utilizando el id de transacción, para esto utilizará un canal https usando JSON y encriptando el atributo data con AES EAX + PKCS1_OEAP. La encripción se crea usando la llave publica del SIFVA para la aplicación.
Se realizan las mismas verificaciones del paso 4 del proceso de autenticación y además se verifica que el id de transacción haya sido suministrado por SIFVA. En caso de que alguna de estas verificaciones falle SIFVA devolverá un error.
Se consulta en la Base de datos usando el id de transacción y se devuelve el resultado almacenado, mediante el mismo canal usando JSON y encriptando el atributo data con AES EAX + PKCS1_OEAP. Se utiliza la llave pública de la aplicación para encriptar la comunicación (nunca publicada).
En caso de que la información suministrada indique que el usuario está correctamente autenticado la aplicación redireccionará a una vista autenticada.
Flujo de Firma¶

El usuario navega dentro de la plataforma de la institución hasta que requiere alguna firma, en ese punto se le despliega un botón qien al hacer click envía una petición post y muestra un modal notificando al usuario que espere.
La plataforma de la institución es la encargada de saber que es lo que el usuario desea firma y debe enviarlo mediante alguna de las bibliotecas de comunicación con dfva utilizando un canal https vía JSON y encritpta en el atributo data la información, usando AES EAX + PKCS1_OEAP.
Dentro de SIFVA se verifica que:
La institución está registrada y activa
La URL de notificación está registrada o la aplicación fue inscrita sin URL de notificación (para aplicaciones no web).
El certificado está vigente y es válido.
Los datos pueden ser desencriptados usando la llave privada de SIFVA asignada a la aplicación.
La suma de verificación de los datos son iguales.
En caso de que alguna de estas verificaciones falle SIFVA devolverá un error.
La petición es almacenada en la base de datos y enviada mediante PyFVA al servicio de FVA del BCCR utilizando un canal SINPE.
Cuando se recibe la respuesta del FVA el código se guarda en la base de datos actualizando la información de la petición.
La respuesta se envía a la institución mediante el mismo canal usando JSON y encriptando el atributo data con AES EAX + PKCS1_OEAP. Se utiliza la llave pública de la aplicación para encriptar la comunicación (nunca publicada).
El código de identificación se le muestra al usuario y el usuario mediante el cliente de firma del BCCR firma la petición de firma.
El FVA del BCCR notifica a SIFVA que el usuario ha firmado la autenticación, una vez que llega a SIFVA se almacena en la base de datos.
Si la aplicación provee una URL de notificación se envía la notificación usando JSON y encriptando el atributo data con AES EAX + PKCS1_OEAP. Se utiliza la llave pública de la aplicación para encriptar la comunicación (nunca publicada).
Una vez la aplicación de la institución es notificada la aplicación realizará lo que necesite con el documento firmado.
Mientras tanto periódicamente se eliminan los datos de las peticiones vencidas guardando dentro de un archivo de log las peticiones eliminadas.
Flujo de estado de petición de firma¶

Este flujo es idéntico al flujo de chequeo del autenticación, la única diferencia corresponde a los datos entregados como respuesta, en los cuales se agrega el documento firmado si existe.
Flujo de verificación¶

El usuario interactua con la aplicación y por alguna razón la aplicación requiere verificar un certificado o un documento.
La aplicación mediante alguna de las bibliotecas de comunicación con dfva envía la petición utilizando un canal https vía JSON y encritpta en el atributo data la información, usando AES EAX + PKCS1_OEAP.
SIFVA envía mediante PyFVA al servicio de FVA del BCCR utilizando un canal SINPE. No se almacena en DB
Se recibe la respuesta por parte de FVA del BCCR.
La respuesta se envía a la institución mediante el mismo canal usando JSON y encriptando el atributo data con AES EAX + PKCS1_OEAP. Se utiliza la llave pública de la aplicación para encriptar la comunicación (nunca publicada).
Diagrama de clases¶
Paquetes¶
Existe una relación entre los paquetes que se describe a continuación
Institución
Personas
Manejador de certificados y Simple CA
Clases¶
DFVA se divide en 2 secciones; personas e instituciones, cada una de éstas se subdivide en 3 los cuales corresponde a
Institución
Personas
Manejador de certificados y Simple CA
Riesgos identificados¶
Los riesgos aquí descritos responden a escenarios y comportamientos de SIFVA que podrían llevar a un riesgo para la implementación, este lugar no es una lista de vulnerabilidades conocidas y todos los riesgos descritos han sido tratados y mitigados, pero en honor al trabajo realizado en este proyecto y en aras de demostrar que los desarrolladores de SIFVA nos tomamos en serio la seguridad hacemos público aquellos riegos identificados que podrían poner en peligro la implementación de este software.
Almacenamiento¶
Almacenamiento de llaves y certificados¶
Las llaves privadas de los servicios se guardan en la base de datos, por ello todas llaves privadas usadas por los servicios (no las llaves privadas de las aplicaciones) son almacenadas en la base de datos.
Mitigación
Para mitigar este riesgos se realiza:
Se Guardan encriptadas las llaves y certificados de la institución en la base de datos utilizando AES Modo EAX.
Se utiliza SECRET_KEY de Django para generar una llave de encripción para AES.
No se almacela la llave privada de la aplicación.
Aseguramiento de la base de datos en producción
Almacenamiento de peticiones y respuestas de firma¶
Las peticiones al BCCR FVA deben esperar a la respuesta del BCCR que tiene como política “No nos llame, nosotros lo llamamos”. Por ello deben almacenarse en una base de datos. Por ello existe el riesgo que la información de las peticiones almacenadas en la base de datos puedan ser accedidas por extraño si la configuración del manejador de base de datos presenta alguna vulnerabilidad.
Además afecta el rendimiento de consulta de peticiones con respecto al número de peticiones por minuto en el sistema.
Mitigación
Almacenar las peticiones por un tiempo fijo pero configurable, para autenticación por defecto se espera 5 minutos y para firma 20 minutos.
Aseguramiento de la base de datos en producción
Indexación de modelos de peticiones
Almacenamiento de bitácoras y auditoría¶
SIFVA y PyFVA poseen un completo sistema de bitácoras, haciendo uso completo de Django logging emitiendo mensajes en los niveles Información, Debug, Warning, Error. Por defecto se guardan las bitácoras en disco provocando 2 afectaciones; 1) llenar el disco con logs, 2) fuga de información producto de los logs
Mitigación
Configurar adecuadamente el sistema de logs, revisar Django logging y configurar un sistema de compresión y rotación de logs.
Almacenamientos de peticiones HTTP¶
Al firmar un documento se requiere que se envíen en el mensaje REST vía POST. Normalmente los servidores de contenido como Apache o Nginx almacenan las peticiones en memoria pero limitan el tamaño, y si se deseea aumentar el tamaño se utiliza el sistema de archivos. Así existe el riesgo de que alguien intente aprovechar esta particularidad para incrustar código malicioso e intentarlo ejecutar desde el sistema de archivos del sistema operativo.
Mitigación
Debe mitigarse a nivel de implementación del servicio y configurando adecuadamente Nginx o Apache.
Serialización y deserialización de comunicaciones¶
Deserialización de Json¶
Toda la comunicación entre SIFVA y las instituciones o personas se realiza utilizando JSON, por lo que alguien podría intentar insertar código malicioso para hacer romper los mecanismos de deserialización y con ello afectar el servicio.
Mitigación
SIFVA utiliza la última versión de Django Rest Framework y confía en la seguridad de este proyecto en el manejo de deserialización JSON.
Serialización de XML (Pyfva)¶
Un atacante podría intentar construir una petición maliciosa que rompa el serializador de XML para incrustar información que altere el comportamiento de la petición a nivel de BCCR FVA.
Mitigación
Se confía en la biblioteca Soapfish para la elaboración de XML.
La deserialización de XML se confía en que el único que envía XML es el BCCR.
Disponibilidad¶
Sustitución del servicio¶
SIFVA es código abierto y libre, por lo que cualquiera puede configurar una instalación e intentar hacerse pasar por SIFVA válido.
Mitigación
Doble uso de llaves RSA y el cifrado de las comunicaciones ayuda a mitigarlo. La llave privada de la apliación solo la debería conocer la aplicación y la llave privada del servicio solo la conoce SIFVA por lo que un sustituto no puede desencriptar las peticiones o enviar respuestas falsas.
Cada institución debe crear mecanismos necesarios para resguardar las llaves RSA y los certificados.
Continuidad del servicio¶
SIFVA no provee ninguna herramienta para prevenir ataques de denegación de servicio.
Mitigación
SIFVA está implementado para poder lanzarse en sistema distribuidos y balanceados, por lo que una buena infraestructura puede mitigar este tipo de ataques.
SIFVA No utiliza sesiones de estado, y cada petición se inicia y termina en una operación atómica.
Si los servicios del BCCR no están disponibles SIFVA no funciona.
Mitigación
SIFVA siempre enviará un mensaje de error al cliente indicando que la transacción no se pudo realizar, por lo que el servicio de SIFVA segurá disponible.
Integridad¶
Integridad de las peticiones¶
Algún atacante podría intentar un Man in the Middle para alterar el contenido de las peticiones y respuestas. Además una aplicación podría proponer hacer una petición por un canal no seguro.
Mitigación
SIFVA, podría ser implementado sobre HTTP sin perder la integridad y confidencialidad de los datos, gracias al doble mecanismo de encripción. Aun así se recomienda encarecidamente utilizar HTTPS en producción.
Integridad de las respuestas del BCCR FVA¶
Un atacante podría hacerse pasar por el BCCR FVA y emitir respuestas a peticiones para por ejemplo suplantar identidad o falsificación de documentos.
Mitigación
SIFVA posee una variable de configuración obligatoria llamada ALLOWED_BCCR_IP donde se especifican las direcciones IP de los servidores del BCCR que envían respuestas, cualquier IP que no esté listada en esta variable se le denegará el acceso.
Confidencialidad¶
Suplantación de identidad¶
Personas:
Alguien podría intentar hacerse pasar por otra persona.
Mitigación
Toda petición a SIFVA es encriptada usando el mecanismo provisto por el dispositivo PKCS11 y verificado usando el certificado digital. Por lo tanto la autenticación de la persona es inequivoca.
Instituciones:
Alguna institución enviar peticiones diciendo ser otra institución.
Debido al doble sistema de encripción, para poder ser una institución valida se debe encriptar y desencriptar con las llaves RSA provistas, cualquier otra llave no importa si es válida para otra institución no lo será si el código de la institución es modificado.
Como hacer un deploy completo para desarrollo de la infraestructura¶
Esta documentación es para la construcción de SIFVA y los diferentes servicios requeridos. Se construye a partir de docker, la instalación del mismo está fuera del alcance de esta bitácora, ver https://docs.docker.com/engine/install/debian/.
Debe tener los siguientes proyectos en una carpeta común:
dfva
fvabccr_simulador
Creación de las imágenes¶
Dentro de fvabccr_simulador ejecute:
docker build -t dfva/fva_bccr .
Dentro de dfva ejecute:
docker build -t dfva/dfva .
¿Cómo Contribuir?¶
Entorno de desarrollo¶
Para poder desarrollar SIFVA core necesita tener:
Lector PKCS11
Firma digital de Costa Rica
Simulador de FVA.
Entorno instalado
Antes de proceder con cualquier cambio ejecute las pruebas en su entorno y asegurese que todas corran.
Testing¶
Debe crear las siguientes variables de entorno antes de correr una prueba.
export PKCS11_PIN=<PIN de desbloqueo de la tarjeta digital>
export PYTHONPATH=:$PYTHONPATH:<ruta del cliente SIFVA de personas>/dfva_client
Ejecute las pruebas
python manage.py test
Nota
Es importante que el PIN sea correcto de lo contrario bloqueará la tarjeta y no podrá utilizarla más.
Advertencia
Asegurese de correr el simulador de FVA y que el la respuesta automática para el certificado sea exitosa con el número de cédula de la tarjeta.
Recuerde que una contribución con pruebas será mejor aceptada y contribuye a la estabilidad del sistema.
También puede hacer pruebas individuales ejecutando por ejemplo.
python manage.py test authenticator.tests.test_check_authenticator_institution.CheckAuthenticatorInstitutionCase.test_authenticate_check
Reportar Issues¶
Utilize los issues de github para reportar cualquier problema encontrado en SIFVA.
Por favor usar la sección de issues de cada cliente si el problema es del cliente y no del core de SIFVA.
Pull Request¶
Todos son bienvenidos utilizando la sección de pull request de github.