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

Instituciones

Conexión con el BCCR (interno)

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

_images/autenticacion_institucion.gif
  1. El usuario ingresa a la plataforma de la institución y se le despliega un modal donde se le pide la identificación

  2. La identificación se envía a la plataforma de la institución

  3. 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.

  4. 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.

  1. La petición es almacenada en la base de datos y enviada mediante PyFVA al servicio de FVA del BCCR utilizando un canal SINPE.

  2. 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.

  3. 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).

  4. 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.

  5. 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.

  6. 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).

  7. Una vez la aplicación de la institución es notificada se autentica al usuario y se redirecciona al usuario a una vista autenticada.

  8. 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

_images/autenticacion_check_institution.gif

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.

  1. 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.

  2. 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.

  3. 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).

  4. 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

_images/firma_institucion.gif
  1. 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.

  2. 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.

  1. La petición es almacenada en la base de datos y enviada mediante PyFVA al servicio de FVA del BCCR utilizando un canal SINPE.

  2. 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.

  3. 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).

  4. 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.

  5. 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.

  6. 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).

  7. Una vez la aplicación de la institución es notificada la aplicación realizará lo que necesite con el documento firmado.

  8. 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

_images/firma_check_institution.gif

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

_images/verificacion_institucion.gif
  1. El usuario interactua con la aplicación y por alguna razón la aplicación requiere verificar un certificado o un documento.

  2. 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.

  3. SIFVA envía mediante PyFVA al servicio de FVA del BCCR utilizando un canal SINPE. No se almacena en DB

  4. Se recibe la respuesta por parte de FVA del BCCR.

  5. 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.