SISTEMA CRIPTOGRÁFICO PARA ALMACENAMIENTO Y TRANSPORTE DE ...
Transcript of SISTEMA CRIPTOGRÁFICO PARA ALMACENAMIENTO Y TRANSPORTE DE ...
1
SISTEMA CRIPTOGRÁFICO PARA ALMACENAMIENTO Y TRANSPORTE DE INFORMACIÓN BASADO EN ÁLGEBRA DE
CURVAS HIPERELÍPTICAS
CARLOS EDUARDO CORTÉS OSORIO
UNIVERSIDAD DE SAN BUENAVENTURA CALI
FACULTAD DE INGENIERÍA PROGRAMA DE INGENIERÍA ELECTRÓNICA
SANTIAGO DE CALI, 2016
2
SISTEMA CRIPTOGRÁFICO PARA ALMACENAMIENTO Y TRANSPORTE DE INFORMACIÓN BASADO EN ÁLGEBRA DE
CURVAS HIPERELÍPTICAS
CARLOS EDUARDO CORTÉS OSORIO
Director
Ing. Oscar Casas García, M.Sc.
Codirector
Ing. Vladimir Trujillo Olaya, Ph.D.
UNIVERSIDAD DE SAN BUENAVENTURA CALI
FACULTAD DE INGENIERÍA PROGRAMA DE INGENIERÍA ELECTRÓNICA
CALI, 2016
3
_________________________
Nota de aceptación
_________________________ Ing. Oscar Casas García, M.Sc.
_________________________ Ing. Vladimir Trujillo Olaya, Ph.D.
_________________________ Firma del jurado
_________________________ Firma del jurado
4
AGRADECIMIENTOS
Quiero agradecer al ingeniero Oscar Casas García por su colaboración y
disposición para guiarme a lo largo del proyecto así como también a mi asesor
el Doctor Vladimir Trujillo quien estuvo pendiente del proyecto en todas sus
etapas.
A todos los profesores del programa incluyendo laboratoristas que de una u
otra manera aportaron conocimiento no solo teórico y práctico sino también una
formación para la vida.
A mi familia que con su sacrificio lograron que se cumpliera esta meta.
5
DEDICATORIA
A mis padres y hermana, quienes con amor y sacrificio lograron sostenerme
tanto económicamente como espiritualmente para cumplir esta meta. A mi
novia por su constante apoyo, infinitas gracias.
6
TABLA DE CONTENIDO
Pág. CAPÍTULO 1 – INTRODUCCIÓN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.1 ANTECEDENTES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.2 MOTIVACIÓN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.3 OBJETIVOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 1.4 CONTRIBUCIÓN. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 1.4 ORGANIZACIÓN DEL DOCUMENTO . . . . . . . . . . . . . . . . . . . . . . . . 15 CAPÍTULO 2 - ANTECEDENTES MATEMÁTICOS. . . . . . . . . . . . . . . . . 17 2.1 CONCEPTOS BÁSICOS DE ÁGEBRA ABSTRACTA. . . . . . . . . . . . . 17 2.1.1 Grupo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 2.1.2 Cuerpo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 2.1.3 Cuerpo finito GF(q). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 2.1.4 Cuerpo finito binario GF( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.2 CONCEPTOS BÁSICOS PARA EL ALGORITMO TWOFISH. . . . . . . 20
2.2.1 Cuerpo finito GF( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.2.2 Suma en cuerpo finito GF( ) . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.2.3 Multiplicación en cuerpo finito GF( ) . . . . . . . . . . . . . . . . . . . . 22
2.3 ÁLGEBRA DE CURVAS HIPERELÍPTICAS . . . . . . . . . . . . . . . . . . . . 24 2.3.1 Curvas hiperelípticas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.3.2 Operación de grupo para curvas hiperelípticas . . . . . . . . . . . . . 25 2.3.3 Divisor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 2.3.4 Variedad jacobiana. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 2.3.5 Representación Mumford . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 2.3.6 Operaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.3.7 Suma y doblado de divisores . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 2.3.8 Multiplicación escalar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 CAPÍTULO 3 - ALGORITMO TWOFISH. . . . . . . . . . . . . . . . . . . . . . . . . . 31 3.1 ENCRIPTACIÓN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 3.1.1 Función F . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 3.1.1.1 Función g. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 3.1.1.2 S-boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 3.1.1.3 Permutaciones y . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 3.1.1.4 Matriz de máxima distancia de separación . . . . . . . . . . . 36 3.1.2 Transformada PHT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 3.2 CLAVES. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 3.2.1 Sub claves y . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3.2.2 Sub claves . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 3.3 DESENCRIPTACIÓN. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
7
CAPÍTULO 4 - PROTOCOLO DE INTERCAMBIO DE CLAVES DIFFIE- HELLMAN EN CURVAS HIPERELÍPTICAS. . . . . . . . . . . . . . . . . . . . . . .
41
4.1 PROTOCOLO DE INTERCAMBIO DE CLAVES DIFFIE-HELLMAN . 41 4.2 PROTOCOLO DE INTERCAMBIO DE CLAVES PARA CURVAS HIPERELÍPTICAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
42
4.2.1 Parámetros iniciales. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 4.2.2 Protocolo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3 LIBRERIAS USADAS PARA LA IMPLEMENTACIÓN EN LENGUAJE C. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.1 NTL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.2 G2HEC. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
43 44 44 45
5. IMPLEMENTACIÓN DEL SISTEMA CRIPTOGRAFICO BASADO EN CURVAS HIPERELIPTICAS Y TWOFISH . . . . . . . . . . . . . . . . . . . . . . . .
48
5.1 DESCRIPCIÓN GENERAL DEL SISTEMA. . . . . . . . . . . . . . . . . . . . . 48 5.1.1 Configuración. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 5.1.2 Inicio de sesión . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 5.1.3 Intercambio de clave . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 5.1.4 Cifrado de la información y fin de sesión. . . . . . . . . . . . . . . . . . . 55 6. PRUEBAS Y RESULTADOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 5.1 INTERCAMBIO DE CLAVE. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 5.1.1 Suma y Doblado de divisores . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 5.1.2 Multiplicación Escalar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 5.2 ENCRIPTACIÓN Y DESENCRIPTACIÓN. . . . . . . . . . . . . . . . . . . . . . 59 5.3 COMPARACIÓN CON OTRAS IMPLEMENTACIONES. . . . . . . . . . . 61
7. CONCLUSIONES Y TRABAJO FUTURO. . . . . . . . . . . . . . . . . . . . . . . 62 7.1 CONCLUSIONES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 7.1 TRABAJO FUTURO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 8. BIBLIOGRAFIA. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 ANEXOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 ANEXO 1: CODIGO PRINCIPAL SERVIDOR. . . . . . . . . . . . . . . . . . . . . . 65 ANEXO 2: CODIGO PRINCIPAL AMBULANCIA. . . . . . . . . . . . . . . . . . . . 69 ANEXO 3: FUNCIONES IMPLEMENTADAS EN SERVIDOR Y AMBULANCIA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
72
ANEXO 4: IMPLEMENTACION TWOFISH . . . . . . . . . . . . . . . . . . . . . . . . 76
8
LISTA DE TABLAS
Pág.
Tabla 1: Propiedades del grupo aditivo y multiplicativo. . . . . . . . . . . . . . . 17
Tabla 2: Operación binaria XOR. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Tabla 3: Partición del texto de entrada . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Tabla 4: Sustituciones para y . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Tabla 5: Funciones utilizadas de la librería G2HEC. . . . . . . . . . . . . . . . . 46
Tabla 6: Especificaciones técnicas de herramientas usadas para
pruebas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . .
56
Tabla 7: Tiempos medidos en el algoritmo de Cantor en el Computador. 57
Tabla 8: Tiempos medidos en el algoritmo de Cantor en la Raspberry Pi 57
Tabla 9: Tiempos medidos en el método de Multiplicación Escalar de
Montgomery en el Computador. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
58
Tabla 10: Tiempos medidos en el método de Multiplicación Escalar de
Montgomery en la Raspberry Pi. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
58
Tabla 11: Tiempos medidos en la encriptación en el Computador. . . . . . 59
Tabla 12: Tiempos medidos en la encriptación en la Raspberry Pi . . . . .
Tabla 13: Comparación con otras implementaciones para la
encriptación usando algoritmo TOWFISH . . . . . . . . . . . . . . . . . . . . . . . . .
Tabla 14: Comparación con otras implementaciones para Multiplicación
escalar en curvas hiperelípticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Tabla 15: Comparación con otras implementaciones para la suma y
doblado de divisores en curvas hiperelíticas . . . . . . . . . . . . . . . . . . . . . .
59
61
61
61
9
LISTA DE FIGURAS
Pág.
Figura 1: Curva hiperelÍptica 24
Figura 2: Operación de grupo para curvas hiperelípticas de género 2. . . 25
Figura 3: Proceso encriptación algoritmo TWOFISH. . . . . . . . . . . . . . . . 31
Figura 4: Intercambio de variables. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Figura 5: Función F. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Figura 6: S-boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Figura 7: Proceso para permutaciones q0 y q1 . . . . . . . . . . . . . . . . . . . . 35
Figura 8: Proceso para obtención de sub claves Ki. . . . . . . . . . . . . . . . . 39
Figura 9: Proceso desencriptacion TWOFISH. . . . . . . . . . . . . . . . . . . . . 40
Figura 10: Diagrama de bloques del sistema criptográfico. . . . . . . . . . . . 48
Figura 11: Diagrama de flujo para el inicio de sesión en Servidor . . . . . . 52
Figura 12: Diagrama de flujo para el inicio de sesión en Ambulancia . . . 52
Figura 13: Diagrama de flujo para intercambio de clave en Servidor. . . . 55
Figura 14: Diagrama de flujo para intercambio de clave en Ambulancia .
Figura 15: Foto real del sistema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
55
57
10
LISTA DE ALGORITMOS
Pág. Algoritmo 1: Cantor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Algoritmo 2: Escalera de Montgomery . . . . . . . . . . . . . . . . . . . . . . . . . . 30
Algoritmo 3: Intercambio de clave Diffie-Hellman. . . . . . . . . . . . . . . . . . 42
Algoritmo 4: Intercambio de clave Diffie-Hellman en curvas
hiperelípticas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
43
11
1. INTRODUCCIÓN
1.1 ANTECEDENTES La criptografía se podría dividir en dos grandes grupos: la criptografía simétrica
(Bellare, M et al. 1997), y la criptografía asimétrica (Bellare, M., & Rogaway, P.
1995), donde cada una ofrece características diferentes y dependiendo de la
aplicación, la funcionalidad puede verse beneficiada por alguno de los dos
tipos, además de que existe el caso en que los dos tipos de criptografía
trabajan de manera conjunta, lo que es conocido como criptografía híbrida
(Fujisaki, E., & Okamoto, T. 1999).
La criptografía simétrica es el tipo de criptografía más usada, debido a que fue
la primera técnica utilizada para dar confidencialidad a la información. La
encriptación simétrica implica el uso de una clave única para encriptar y
desencriptar los datos, de manera que tanto el emisor como receptor deben
compartir el conocimiento de la clave secreta. Existen registros de que se
utilizó desde épocas anteriores a Cristo, que empezó con simples sustituciones
mono alfabéticas que permitían encriptar la información, y que únicamente
mediante el conocimiento de la clave se podía revertir el proceso de encriptado
para así tener el mensaje original (V, Kapoor et al. 2000). Luego se empezó a
desarrollar el criptoanálisis en los años 1000 D.C (V, Kapoor et al. 2008),
haciendo que el método por sustituciones mono alfabéticas quedara
desechado, forzando así a mejorar dicha técnica, nace entonces un nuevo
método en el cual las sustituciones eran ya poli alfabéticas (V, Kapoor et al.
2008), lo que llevaba al criptoanálisis a buscar la forma de romper el nuevo
algoritmo. Este círculo es el que ha permitido el avance en la criptografía
puesto que cada vez se buscan nuevas técnicas para proteger la información, y
de generar algoritmos que no puedan ser rotos en un tiempo razonable, puesto
que todo algoritmo puede ser roto (V, Kapoor et al. 2008).
En el año de 1976 los criptógrafos Whitfield Diffie y Martin Hellman publican un
artículo denominado New directions in Cryptography (Diffie, W., & Hellman, M.
12
E. 1976) el cual va a ser la base fundamental para la creación de una nueva
forma de criptografía, conocida como criptografía asimétrica o de clave pública,
la cual ofrece nuevas formas de encriptar los datos mediante el uso de un par
de claves por cada participante del proceso de comunicación: una clave pública
y una clave privada, mejorando así los procesos críticos como el de compartir
las claves, y la autenticación de los participantes del proceso mediante la firma
digital.
La criptografía asimétrica utiliza dos claves complementarias llamadas clave
privada y clave pública. Los mensajes que son encriptados con una clave
pública necesitan de su correspondiente clave privada para ser desencriptados.
Las claves privadas deben ser conocidas únicamente por su propietario,
mientras que la correspondiente clave pública puede ser dada a conocer
abiertamente. Esto permite garantizar la identidad del emisor y del receptor de
la información.
1.2 MOTIVACIÓN En los años de 1986 y 1987 dos criptógrafos llamados Niels Koblitz y Victor
Miller (Miller, V.1986) (Koblitz, N. 1987) publican artículos por separado acerca
de una nueva forma de criptografía asimétrica llamada criptografía de curva
elíptica, la cual tiene su base en un proceso matemático basado en álgebra
abstracta de curvas dentro de las cuales existe una generalización, llamada
curvas hiperelípticas, estas últimas han sido objeto de estudio, puesto que han
probado ser uno de los métodos más eficientes para la implementación (Lange,
T. 2005), debido a que utilizan claves de encriptación mucho más cortas
(Duquesne, S & Lange, T. 2006) y la rapidez del sistema es notablemente
superior comparada con la de otros tipos de encriptación (Menezes, et al 1997),
añadiendo también que la seguridad del sistema sigue siendo equivalente.
Con el desarrollo de la computación, la criptografía ha avanzado a pasos
agigantados debido a que las técnicas utilizadas actualmente, tienen una base
matemática, donde las operaciones a realizar necesitan eficiencia al momento
13
de realizar los cálculos, y una capacidad de memoria necesaria para almacenar
la claves (Fúster, A. et al 2001), añadiéndole a esto la necesidad de un canal
de comunicación robusto para que la información que viaje por el medio, llegue
íntegra y pueda ser procesada.
En coherencia con lo escrito anteriormente en la Universidad de San
Buenaventura Cali, el Grupo LEA desarrolla un proyecto de investigación con
título “Plataforma tecnológica para mejorar los procesos de autenticación,
acceso a información clínica y direccionamiento de los pacientes, en
situaciones de emergencia, desde la ambulancia a los centros hospitalarios de
Cali”, el cual consiste como su nombre lo indica, en la implementación de un
plataforma que mejore los procesos que requiere un paciente en el momento
de ser atendido en una ambulancia. La plataforma se basa en un mecanismo
electrónico conectado a un sistema de información, que permite al personal
paramédico entre alguna de sus funciones: “Acceder la historia clínica del
paciente para conocer posibles preexistencias médicas.”
En el acceso a la historia clínica del paciente, se debe prestar especial atención
a los procesos de seguridad informática, puesto que se trata de información
sensible y que no debe ser divulgada. Esto quiere decir que dicha información
es de carácter confidencial y no puede ser manipulada, destruida, o tan
siquiera ser distinguible por cualquier persona o ente que quiera obtenerla de
manera ilegal; pues es una información privada que contiene el recorrido
médico del paciente desde su nacimiento, siendo así un documento de un alto
nivel de importancia para procedimientos médicos. Por tal razón es necesario
el uso de técnicas de encriptación que permita generar seguridad,
confidencialidad e integridad de los datos, además de ser robusta ante las
distintas amenazas informáticas que puedan presentarse.
1.3 OBJETIVOS Siendo consecuentes con lo anterior este proyecto tiene como objetivo general
implementar un sistema de encriptación de clave pública, para almacenamiento
14
y transporte de información basado en curvas hiperelípticas, el cual permita
proteger la historia clínica del paciente.
Para cumplir a cabalidad con este proyecto se subdividió en los siguientes
objetivos específicos.
Realizar un estado del arte acerca de sistemas de encriptación basados
en curvas hiperelípticas.
Diseñar el software y hardware necesario para el sistema criptográfico
basado en algebra de curvas hiperelípticas.
Implementar el sistema criptográfico basado en algebra de curvas
hiperelípticas.
Realizar las pruebas necesarias para corregir errores en el sistema y
lograr el correcto funcionamiento concluyendo así con optimización del
mismo.
Divulgar los resultados obtenidos en el proyecto y culminar con la
realización del documento final en el cual se describirán los resultados
generales del proyecto que puedan servir para futuras modificaciones
y/o aplicaciones.
1.4 CONTRIBUCIÓN La principal contribución de este trabajo es la implementación de un sistema
criptográfico que permite mediante un algoritmo el establecimiento de una clave
común para dos entes que desean comunicarse de manera segura, y que
mediante otro algoritmo se cifre la información que viajará por el medio. Para
lograr esto se empezó por decidir de qué manera estructurar nuestro sistema
criptográfico y gracias a la recopilación bibliográfica se concluyó que este
debería estar compuesto por los dos tipos de criptografía, para la selección del
algoritmo de criptografía simétrica, se realizó una revisión a un proyecto
desarrollado por el grupo LEA con título “Pruebas de rendimiento para los
15
esquemas de encriptación finalistas del AES” y se pudo observar el algoritmo
que mejor rendimiento obtuvo en dichas pruebas, así pues este trabajo
implementa dicho algoritmo, denominado: TWOFISH.
Por otra parte, se vio la necesidad de implementar un algoritmo que permitiera
compartir de una manera rápida y segura la clave a utilizar en nuestro algoritmo
de clave simétrica (TWOFISH), es aquí donde aparece la criptografía basada
en algebra de curvas hiperelítpicas, puesto que con la información recopilada
se llegó a la conclusión de que esta técnica permite una mayor velocidad
gracias a que las claves a utilizar ocupan menor espacio en memoria, una vez
seleccionada la técnica en este trabajo se implementó el algoritmo más
utilizado para el intercambio de claves, denominado DIFFIE-HELLMAN KEY
EXCHANGE y en su variación para curvas hiperelípticas DIFFIE-HELLMAN
HIPERELÍPTIC CURVE CRIPTOGRAPHY (DHHECC).
1.5 ORGANIZACIÓN DEL DOCUMENTO En el Capítulo 1, titulado “INTRODUCCIÓN” se enuncian los cambios a través
de la historia acerca de la criptografía, se define las causas que generaron el
desarrollo de este trabajo, se enlistan los objetivos a desarrollar y se habla
acerca de lo que se logra con la finalización de este proyecto.
En el capítulo 2, titulado ANTECEDENTES MATEMÁTICOS se muestra la base
matemática que se utiliza en la implementación de los algoritmo, para ello se
introduce al lector en los diferentes conceptos matemáticos utilizados en la
criptografía en general, definiendo Grupo y Cuerpo, luego se explica el grupo
finito utilizado, y la manera de sumar y multiplicar para el algoritmo TWOFISH,
después se definen los conceptos de curva hiperelíptica, divisor y su
representación Mumford, así como también se define la variedad jacobiana,
para luego entender cómo se realiza la operación de grupo, en este capítulo se
enuncia el algoritmo de Cantor para la suma y doblado de divisores, así como
el algoritmo de multiplicación escalar de Montgomery.
16
En el capítulo 3, titulado ALGORITMO TWOFISH se centra en la explicación
del algoritmo TWOFISH, mostrando un diagrama de bloques para la
encriptación, luego se procede a explicar de manera detallada cada una de las
funciones que componen este diagrama de bloques, como lo son la función F,
función g, las S-boxes y permutaciones, así como también se describe el
proceso para la obtención de las claves, y por último la explicación del proceso
de desencriptación.
En el capítulo 4, titulado PROTOCOLO DE INTERCAMBIO DE CLAVES
DIFFIE-HELLMAN EN CURVAS HIPERELÍPTICAS se presenta en una primera
instancia el algoritmo de intercambio de claves clásico propuesto por Whitfield
Diffie y Martin Hellman, y luego se explica de manera detallada su variante para
curvas hiperelípticas, definiendo parámetros iniciales y el protocolo a seguir.
En el capítulo 5, titulado IMPLEMENTACIÓN DEL SISTEMA
CRIPTOGRAFICO BASADO EN CURVAS HIPERELIPTICAS Y TWOFISH se
expone el diagrama general del sistema en bloques, y se procede a explicarlos
de manera detallada con diagramas de flujo y codigo, así pues se muestra la
manera en que se deben configurar parámetros iniciales, para proceder a
iniciar sesión y compartir información encriptada, y posteriormente cerrar la
sesión, en este capítulo se comienza a sumergir al lector en la algoritmia del
sistema.
En el capítulo 6, titulado PRUEBAS Y RESULTADOS se muestran las pruebas
de tiempo realizados a las operaciones criticas del sistema, como lo son la
suma de divisores, la multiplicación escalar y el proceso de encriptación, todas
estas pruebas se exponen en tablas de valores y se comparan con
implementaciones realizadas por otros autores.
En el capítulo 7, titulado CONCLUSIONES Y TRABAJO FUTURO se muestran
las conclusiones hechas por el autor acerca del proyecto y se presentan las
opciones de trabajo futuro del mismo.
17
2. ANTECEDENTES MATEMÁTICOS
A continuación se presentará la matemática básica que permite un
acercamiento al mundo de la criptografía y posteriormente se presentarán las
matemáticas utilizadas en el algoritmo TWOFISH y las utilizadas en el
algoritmo DHHECC.
2.1 CONCEPTOS BÁSICOS DE ÁLGEBRA ABSTRACTA
2.1.1 Grupo Un grupo consiste en un conjunto con una operación binaria, para
este caso aditivo donde , es decir que todo elemento del grupo
operado con otro elemento del mismo, da como resultado un elemento
perteneciente al grupo. A continuación se presenta en la Tabla 1 sus
propiedades así como también para el conjunto bajo la operación multiplicativa
.
Tabla 1: Propiedades del grupo aditivo y multiplicativo
GRUPO
PROPIEDAD ADITIVO MULTIPLICATIVO
Asociativa
para todo
para
todo
Elemento de identidad
para todo
para todo
Elemento inverso para todo
para todo
Conmutativa
para todo
para todo
Las operaciones de grupo son usualmente llamadas adición ó
multiplicación . Para la primera instancia, el grupo es llamado grupo aditivo, el
18
elemento de identidad para el grupo aditivo es , y el elemento inverso es
– . En la segunda instancia el grupo es llamado grupo multiplicativo, el
elemento de identidad para el grupo multiplicativo es , y el elemento
inverso de a es . El grupo es finito si es un conjunto finito, en ese caso el
número de los elementos en es llamado el orden del conjunto u orden de
(Fúster, A et al. 2001).
2.1.2 Cuerpo Un cuerpo es un conjunto de elementos con dos operaciones binarias,
representadas como, adición y multiplicación , que presentan las siguientes
propiedades:
- Los elementos de forman un grupo abeliano bajo la operación .
- Los elementos del conjunto , el cual es un conjunto que contiene
todos los elementos del conjunto pero no cumple la identidad aditiva,
forman un grupo abeliano bajo la operación . Además, satisface las
propiedades asociativa y conmutativa
- La propiedad distributiva aplica a dos operaciones
, para .
Si el cuerpo tiene un conjunto de elementos finito, se llama un cuerpo finito o
cuerpo de Galois y se representa como .
2.1.3 Cuerpo finito
También conocido como campo de Galois, hace referencia a un cuerpo en el
cual existen finitamente muchos elementos, y debe cumplirse que bajo la
operación de multiplicación debe ser abeliano (conmutativo) y cada elemento
19
excepto el cero debe tener un inverso multiplicativo. Es particularmente útil en
traducir datos de computadora, en su representación de forma binaria. Lo que
quiere decir que los datos de computadora consisten en una combinación de
dos números, 0 y 1, los cuales son los componentes en un cuerpo finito el cual
su número de elementos es dos. Representar los datos como un vector en un
cuerpo finito permite operaciones matemáticas para codificar los datos de una
manera fácil y efectiva (Benvenuto, C. 2012).
Ejemplo:
El cual consiste de 5 elementos donde cada uno de ellos es un polinomio de
grado 0 (una constante).
2.1.4 Cuerpo finito binario Cuando para cualquier positivo mayor a uno, el cuerpo se
llama cuerpo finito binario. Los elementos del subcuerpo pueden ser
representados por señales lógicas 0 y 1, lo cual permite representar cadenas
binarias que pueden ser implementadas eficientemente.
Los elementos de un cuerpo finito están definidos como
Donde ℙ y ℤ +. El orden del cuerpo está definido por mientras que
es llamado la característica del cuerpo. También se puede notar que el grado
del polinomio de cada elemento es como máximo .
20
Ejemplo:
El cual consiste de = 8 elementos donde cada uno de ellos es un polinomio
de grado máximo 2 evaluado en 2.
2.2 CONCEPTOS BASICOS PARA EL ALGORITMO TWOFISH
2.2.1 Cuerpo finito Para el algoritmo TWOFISH los campos utilizados son de tipo debido a
que los restos del módulo 2 serán 0 y 1, permitiendo así una representación
binaria, es decir que terminará siendo el tamaño en bits de cada elemento.
Como las operaciones a realizar en el algoritmo TWOFISH son a nivel de byte
(8 bits), se utilizará el campo , así pues un byte se denotaría como los
bits y se denotaría como un polinomio:
Ejemplo:
Un byte con valor en hexadecimal “45”:
Binario:
Polinomio:
2.2.2 Suma en cuerpo finito En los campos las operaciones se realizan modulo , debido a que son
campos finitos y los resultados no pueden desbordarse de los elementos
existentes. Al utilizar los campos , se hace notorio observar que dichos
21
resultados pueden ser solamente haciendo que las operaciones se
puedan llevar a simples operaciones de compuertas lógicas.
Para el caso de la suma y la resta se logran realizar utilizando una compuerta
XOR.
Tabla 2: Operación binaria XOR
XOR
Entrada 1 Entrada 2 Salida
0 0 0
0 1 1
1 0 1
1 1 0
Se observa que para sumar dos polinomios bastaría con aplicar la función XOR
a cada elemento, es decir si se tienen dos { } y
{ } el resultado { } se obtendría de operar
siendo el bit correspondiente.
Ejemplo:
En polinomios seria:
+
= =
22
2.2.3 Multiplicación en cuerpo finito La multiplicación en los campos necesita de polinomios irreducibles,
debido a que al operar, estos posiblemente generen elementos que no estén
dentro del mismo cuerpo es decir potencias mayores a . Para el caso del
algoritmo TWOFISH, este utiliza dos polinomios irreducibles que se usan en
diferentes partes del algoritmo (Schneier, B., et al. 1998):
Entiéndase polinomio irreducible aquellos que su único divisor es 1 ó el mismo.
Ejemplo:
Sean los polinomios :
Con polinomio irreducible:
De se obtiene que:
Se tiene que:
) * )
(1)
23
Se observa que están por fuera del cuerpo por lo que
reduciéndolo con el polinomio se tiene:
1. De donde conocemos del polinomio irreducible
( ) = (2)
2. De donde conocemos del polinomio irreducible
( ) =
3. De donde conocemos del polinomio irreducible
( ) =
Reemplazo en (2)
Entonces:
(3)
Se repite el proceso para
1. De donde conocemos del polinomio irreducible
( ) =
Entonces:
(4)
Reemplazamos (3) y (4) en la ecuación (1)
= =
24
2.3 ÁLGEBRA DE CURVAS HIPERELÍPTICAS
2.3.1 Curvas hiperelípticas Una curva hiperelíptica de género sobre un campo está definida por la
siguiente ecuación:
Dónde:
- es un polinomio monoico de grado .
- es un polinomio con grado máximo .
- No existen soluciones ̅ ̅ que satisfagan
simultáneamente las ecuaciones (Menezes et al, 1996):
En la Figura 1 se muestra un ejemplo de curva hiperelíptica de género y
, definida sobre un cuerpo primo
Figura 1: Curva hiperelíptica
Fuente: (Casas, O. 2010)
25
2.3.2 Operación de grupo para curvas hiperelípticas En curvas hiperelípticas no es posible realizar operaciones aritméticas con los
puntos obtenidos dentro de ellas, es por esto que se necesita de sumas finitas
de puntos y es ahí donde la operación de grupo resulta de la suma de los
coeficientes de dicha suma, denotada por la siguiente ecuación:
[ ] [ ]
Para facilidad del lector, se representa en la Figura 2, una operación de grupo
de manera gráfica para una curva de genero 2 sobre el conjunto de los
números reales.
Figura 2: Operación de grupo para curvas hiperelípticas de género 2
Fuente: (Duquesne, S, & Lange, T. 2006)
Como se enuncio anteriormente para obtener un elemento dentro de la curva
que se pueda operar con otro, es necesaria la obtención de al menos dos
26
puntos por cada elemento, es decir que se realiza en una primera instancia la
suma formal y luego se reduce, como se observa en la Figura 2 existen dos
elementos que al sumarse forman un nuevo elemento , a su vez estos
elementos se forman de la siguiente manera [ ] y [ ]
aclarando que son puntos diferentes dentro de la curva . Luego
una función de grado 3 en pasa a través de todos estos 4 puntos
generando así una intersección con dos nuevos puntos ( , , los cuales
al invertirse generan el resultado de la operación, esto se denota entonces por
la siguiente ecuación:
[ ] [ ] [ ]
2.3.3 Divisor Un divisor es una suma formal de puntos en denotada por:
∑ ; ℤ
En la cual en su mayoría de veces es cero, y solamente en un número finito
de ocasiones tiene un valor diferente, este a su vez es denominado el orden del
divisor en el punto , denotado como , y define también el grado
del divisor, al ser la sumatoria de los coeficientes denotado como
∑ .
El conjunto de todos los divisores sobre la curva se denota como , y el
conjunto de todos los divisores de grado cero sobre la curva como y son
un subgrupo de , para el conjunto de los divisores de la curva , bajo
la regla de la adición, crearan un grupo aditivo, definiendo la suma como:
∑ ∑ = ∑
27
Llegados a este punto se observa que se tiene una estructura de grupo aditivo,
pero estos por si solos no permiten un tratamiento matemático útil en
criptografía, para obtener una estructura que si lo permita se debe definir una
relación que agrupe a los divisores de grado cero en clases de equivalencia, y
al conjunto cociente formado por estas clases se le denomina variedad
jacobiana de una curva hipereliptica.
2.3.4 Variedad jacobiana El grupo de clase divisor denotado como
, es el grupo resultado de la
división entre los divisores de grado cero , sobre los divisores principales
de la curva. La variedad jacobiana denotada como es un isomorfismo
de la cual si nos permite obtener una estructura de grupo algebraico,
haciendo que se tenga un operación de grupo de manera que permita realizar
cómputos, pero para ello es necesario representar los elementos del jacobiano
de una manera cómoda para lograr operar.
Una de estas formas es la utilización de funciones racionales, al usarse una
representación de coordenadas afines, ó por medio de polinomios, los cuales
representan a un divisor como [ ] si se usan coordenadas proyectivas.
Para este trabajo se utilizan coordenadas proyectivas las cuales permiten
trabajar los elementos del jacobiano por medio de dos polinomios [ ],
esto se logra mediante la representación Mumford.
2.3.5 Representación Mumford La representación Mumford permite interpretar un divisor el cual es una
sumatoria formal de puntos, como un par de polinomios [ ].
Sea (∑ ) , donde Para calcular el par de polinomios
se procede con:
28
∏
∑∏
∏
Estos polinomios tienen las siguientes características:
Es Mónico
De manera que dichos elementos del jacobiano tienen ahora una
representación útil para realizar las operaciones necesarias gracias a la
facilidad de trabajar con los coeficientes de dichos polinomios.
2.3.6 Operaciones La operación más importante para el desarrollo de la criptografía en curvas
algebraicas, es la multiplicación escalar, pues permite operar un entero positivo
con un divisor, esto se logra mediante la utilización de dos operaciones, la
suma de divisores, y el doblado de divisores, actualmente existen diversos
algoritmos que permiten realizar esta función, a continuación se presentan los
algoritmos utilizados en este proyecto.
Estas operaciones resultaran necesarias para la implementación del sistema
criptográfico.
29
2.3.7 Suma y doblado de divisores Para lograr la operación de grupo, en este proyecto se utilizó el algoritmo de
Cantor, el cual permite realizar la suma de dos divisores en representación
Mumford , y puede ser utilizado en curvas de cualquier género
(Cantor, D. 1987), así como también permite doblar un divisor, pues es posible
observar que se realizaría mediante la suma del divisor con el mismo
a continuación en el Algoritmo 1 se presentan los pasos:
Algoritmo 1: Cantor
Algoritmo de Cantor
Entrada: Dos divisores [ ] y [ ] en la curva :
Salida: El divisor reducido único [ ] tal que
Paso 1. [ ]
Paso 2. [
]
Paso 3. , ,
Paso 4.
,
Paso 5. Repetir
Paso 6.
,
Paso 7. ,
Paso 8. Hasta
Paso 9. Hacer mónico
Paso 10. Retornar [ ]
2.3.8 Multiplicación escalar Como se enuncio anteriormente, la multiplicación escalar es la operación más
importante en la criptografía de curvas, existen diversos algoritmos los cuales
según la característica y el género de la curva permiten realizar la operación
30
(Duquesne, S, & Lange, T. 2006), para este proyecto se utilizaron curvas de
género dos y característica prima , y se utilizó el algoritmo denominado
escalera de Montgomery presentado a continuación:
Algoritmo 2: Escalera de Montgomery
Escalera de Montgomery
Entrada: Un divisor [ ] y un entero positivo
Salida: El divisor [ ] [ ]
Paso 1. [ ]
Paso 2. Desde hasta hacer
Paso 3. Si el bit de hacer
Paso 4. [ ]
Paso 5. Si el bit de hacer
Paso 6. [ ]
Paso 7. Retornar
31
3. ALGORITMO TWOFISH
TWOFISH descrito en “Twofish: A 128-bit block cipher” (Schneier, B., et al.
1998), es un algoritmo de cifrado por bloques de 128 bits, con una clave que
puede variar entre 128, 192 y 256 bits. El algoritmo cuenta con dos procesos
para lograr la protección del bloque de datos, en una primera instancia, se
procede a utilizar la clave en un algoritmo generador de subclaves, las cuales
serán utilizadas en el algoritmo de encriptación, el cual consta de 16 rondas
para claves de 128 bits (Schneier, B., et al. 1998), a continuación en la Figura 3
se presenta un diagrama de bloques el cual será la referencia para nuestro
trabajo.
Figura 3: Proceso encriptación algoritmo TWOFISH
32
3.1 ENCRIPTACIÓN Como se observa en la Figura 3, el proceso de encriptación comienza con la
entrada de un bloque de datos de 128 bits, denominado comúnmente texto
plano al cual nos referiremos como , este se divide en 4 paquetes de datos
de 32 bits quedando de la siguiente manera tal como lo muestra la Tabla 3:
Tabla 3: Partición del texto de entrada
La primera acción a realizar en el algoritmo es el llamado blanqueo inicial, el
cual consiste en realizar una operación XOR del paquete con la subclave
, el paquete con la subclave , el paquete con la subclave y por
ultimo el paquete con la subclave (más adelante se observara la manera
de obtener estas subclaves), una vez realizado el blanqueo se observa que las
dos partes más significativas entran a la función más importante del algoritmo,
denominada función F, mientras que las partes menos significativas esperan el
resultado de dicha función para luego operar mediante compuertas XOR dichos
resultados, con la característica de que realiza la operación XOR y luego
procede a rotar un bit a la derecha, y hace en primer lugar la rotación de un
bit a la izquierda y luego la operación XOR.
Una vez realizado esto, se realiza un intercambio con los resultados de las
operaciones realizadas con los cuatro paquetes de datos, a continuación se
presenta en la Figura 4 este proceso:
Figura 4: Intercambio de variables
33
3.1.1 Función F La función F es una permutación realizada en 64 bits, debido a que sus
argumentos de entrada son dos paquetes de datos de 32 bits y el número de
ronda que será necesario para utilizar las subclaves apropiadas, se presenta
en la Figura 5 este proceso:
Figura 5: Función F
En la imagen anterior se puede entonces observar que a dicha función consta
de una rotación de 8 bits, una nueva función denominada función g, la cual
contiene dentro de ella funciones llamadas S-boxes y función MDS, las cuales
se mostraran a continuación, también se observa una nueva función llamada
PHT (Pseudo Hadamard Transformation) y sumatorias mod a las cuales
entran las subclaves donde y en las cuales
es el número de ronda en que se encuentre.
3.1.1.1 Función g La entrada a esta función es un paquete de datos de 32 bits, los cuales se
dividen en 4 paquetes de 8 bits, estos van a las cajas de sustitución
denominadas S-boxes, luego a la matriz de distancia máxima de separación
34
MDS y los resultados individuales se concatenan de nuevo para una salida de
32 bits.
3.1.1.1.1 S-boxes Son 4 cajas de sustitución, en las cuales entra un paquete de datos de 8 bits
donde el paquete de datos más significativo entra en primera instancia hacia
las cajas de permutación donde , al realizar las cuatro
permutaciones se concatena el resultado en el mismo orden en el que se
dividieron los paquetes anteriormente para luego realizar una operación XOR
con las subclaves donde dependiendo de la subclave indicada, a
continuación se muestra gráficamente el proceso en la Figura 6:
Figura 6: S-boxes
3.1.1.1.2 Permutaciones y Las permutaciones y tienen una entrada de 8 bits la cual se divide en dos
nibbles y donde es el nibble más significativo, estas permutaciones son
idénticas en el manejo de estos dos nibbles con la diferencia en que las
sustituciones a realizar, dependen de la permutación en la que se encuentre,
más adelante en la Tabla 4 se observa las correspondientes sustituciones.
35
En la Figura 7 se muestra el algoritmo de las permutaciones mediante
diagramas de bloques:
Figura 7: Proceso para permutaciones y
Los valores de se sustituyen utilizando la Tabla 4, dependiendo de
la permutación en la que se encuentre:
Tabla 4: Sustituciones para y
36
3.1.1.1.3 Matriz de máxima distancia de separación Después de realizado el proceso de las S-boxes, se tiene entonces los
resultados de cada una siendo el resultado de la S-box 0, el resultado de
la S-box 1, el resultado de la S-box 2 y el resultado de la S-box 3,
TWOFISH utiliza una matriz MDS específica para el campo , a la cual
multiplica por los resultados descritos anteriormente, generando así a
, los cuales son paquetes de 8 bits, que al concatenarse siendo
los bits más significativos son el resultado de 32 bits de la función f. Hay que
recordar que para la multiplicación en este campo binario se necesita un
polinomio irreducible definido en (Schneier, B., et al. 1998).
El polinomio irreducible para este caso es:
.
La matriz MDS utilizada es la siguiente:
[
] = [
] [
]
3.1.2 Transformada Pseudo Hadamard Esta función se compone básicamente de una suma modulo y una rotación
de 1 bit a la izquierda, tiene como entradas y de 32 bits cada uno y entrega
dos salidas y calculadas de la siguiente manera:
37
3.2 CLAVES El algoritmo TWOFISH utiliza dos tipos de subclaves a lo largo del proceso,
una de ellas son las subclaves y las cuales son constantes y son
utilizadas en la función g, por otra parte están las subclaves las cuales son
utilizadas en la parte inicial y final del proceso de encriptación y des
encriptación así como también se utiliza un par de ellas en cada una de las 16
rondas que ejecuta el algoritmo, lo que conlleva a deducir que junto con las 8
utilizadas en el blanqueo inicial y final, resultan ser 40 subclaves.
3.2.1 Subclaves y Las sub claves y se obtienen de realizar una multiplicación de una matriz
constante denominada RS, por un paquete de datos de 64 bits
correspondientes de la clave principal de 128 bits del algoritmo, hay que
recordar que al multiplicar en el campo , se necesita de un polinomio
irreducible para poder lograrlo, en este caso el polinomio irreducible es
, a continuación se muestra el proceso para
calcular este par de subclaves:
Para la sub clave :
[
]
= [
]
[
]
38
Para la sub clave :
[
]
= [
]
[
]
Donde los son paquetes de datos de 8 bits provenientes de la clave
principal de 128 bits del algoritmo, y como se puede observar la parte más
significativa de la clave se utiliza para calcular y la parte menos significativa
para , al culminar la operación se procede a concatenar los siendo los
8 bits más significativos.
3.2.2 Sub claves Las subclaves se calculan utilizando una variante de la función f,
denominada función h, esta función tienen como característica que las claves
que se blanquean mediante la operación XOR en las permutaciones, ya no son
las subclaves y , ahora son paquetes de datos del mismo tamaño pero
derivadas directamente de la clave principal del algoritmo, denominadas
cada una de 32 bits siendo los 32 bits más significativos de
la clave, además de ello la rotación de 8 bits hacia la izquierda no se hace al
comienzo como en la función f sino que se realiza al final, agregándole también
una nueva rotación de 9 bits a la izquierda.
A continuación se muestra en la Figura 8 el proceso mediante diagramas de
bloque:
39
Figura 8: Proceso para obtención de sub claves
Como se enuncio anteriormente el algoritmo necesita 40 subclaves, es por ello
que la variable que aparece al inicio de los bloques variara desde 0 hasta 19,
lo que lograría la creación de las subclaves { }.
3.1 DESENCRIPTACIÓN
Los algoritmos de criptografía simétrica como TWOFISH tienen la característica
de que con las funciones ya creadas para encriptar los datos, es posible
desencriptarlos realizando el proceso inverso sin cambiar ninguna función
existente, generando así eficiencia en su implementación, así pues este
proceso se logra realizando unas pocas modificaciones.
A continuación en la Figura 9 se muestra el diagrama de bloques para la
recuperación de la información:
40
Figura 9: Proceso desencriptacion TWOFISH
Como se puede observar en la figura, el proceso cambia en cuanto al uso de
las claves, pues ahora en las rondas se empieza desde la clave hasta la
clave , así como también las rotaciones en las salidas de la función f.
41
4. PROTOCOLO DE INTERCAMBIO DE CLAVES DIFFIE-HELLMAN EN CURVAS HIPERELÍPTICAS
El algoritmo presentado en (Diffie, W., & Hellman, M. 1976), fue el punto de
partida para lo que hoy se conoce como criptografía de clave pública, o
criptografía asimétrica, la base de este algoritmo ha sido utilizada en diversas
técnicas, donde los pasos a seguir se mantienen y son las operaciones
matemáticas que difieren, esto claro está dependiendo de la clase de campo y
grupo finito utilizado.
Para el caso de las curvas hiperelípticas, este algoritmo tiene una variante, en
donde las configuraciones iniciales del algoritmo, son ahora una curva
hiperelíptica y un divisor en el jacobiano de la curva, posterior a ello se procede
como el algoritmo clásico, para entender mejor este procedimiento,
observaremos a continuación dicho algoritmo para luego apreciar la
modificación en la matemática de curvas.
4.1 PROTOCOLO DE INTERCAMBIO DE CLAVES DIFFIE-HELLMAN
Este protocolo permite que dos entes , sin previo conocimiento (es
decir que nunca han estado en contacto), logren establecer una clave común
a través de un medio inseguro, dicha clave posteriormente podrá ser
utilizada por algoritmos de criptografía simétrica, tal como es el caso de
TWOFISH.
Esto se logra teniendo parámetros iniciales y comunes para ambos, para ello
se escoge un numero primo , el cual será el delimitador del campo ℤ , y un
generador ϵ ℤ , donde el tamaño del número primo será el que defina el
tamaño de la clave, una vez hecho esto, se está listo para seguir los siguientes
pasos descritos en el Algoritmo 3.
42
Algoritmo 3: Intercambio de clave Diffie-Hellman
ALICE BOB
Parámetros públicos Alice:
Salida: La clave común
Paso 1.
Paso 2.
Paso 3.
Paso 4.
Paso 5.
Parámetros públicos Bob:
Salida: La clave común
Paso 1.
Paso 2.
Paso 3.
Paso 4.
Paso 5.
Llegados a este punto se obtiene un valor común entre ambas partes, y se ha
logrado establecer la clave que posteriormente utilizaran en algún otro
algoritmo de criptografía simétrica, para el caso de este proyecto, esta clave
será utilizada en el algoritmo TWOFISH.
4.2 PROTOCOLO DE INTERCAMBIO DE CLAVES PARA CURVAS
HIPERELÍPTICAS
Neal Koblitz, creador de la criptografía en curvas hiperelípticas, sugiere en
(Koblitz, N. 1989) la siguiente configuración para el intercambio de claves, cabe
resaltar que es el mismo procedimiento realizado en el protocolo de la sección
anterior con la diferencia ahora de los parámetros iniciales y las operaciones;
ya no son potencias modulares sino multiplicaciones escalares de divisores
reducidos del jacobiano de una curva hiperelíptica con un entero positivo.
4.2.1 Parámetros iniciales
Sean y dos entes que nunca han tenido ningún contacto anterior, y
desean acordar una clave común para su posterior uso, para ello y
deben acordar las ecuaciones y de una curva hiperelíptica:
43
Así como también un número primo el cual será el delimitador del campo de
Galois , posterior a ello, con algún algoritmo conocido, se hayan los
puntos que satisfagan la ecuación , con dichos puntos es posible ahora hallar
un divisor reducido dentro de esta curva, y así obtener el ultimo parámetro
para realizar el intercambio de clave entre estos dos entes. Cabe resaltar que
estos parámetros iniciales los define uno de los dos entes, y se envían por
medio del canal.
4.2.2 Protocolo Para el desarrollo del protocolo, es necesario obtener un algoritmo de
multiplicación escalar como el explicado en la sección 2.3.8 del segundo
capítulo de este trabajo, en el siguiente protocolo se asume que uno de los dos
entes obtuvo de manera correcta los parámetros descritos en la sección
anterior, y están listos para realizar el protocolo definido en el Algoritmo 4.
Algoritmo 4: Intercambio de clave Diffie-Hellman en curvas hiperelípticas
ALICE BOB
Parámetros públicos Alice: Una
curva :
Un divisor [ ]
Salida: La clave común [ ]
Paso 1.
Paso 2.
Paso 3.
Paso 4.
Paso 5.
Parámetros públicos Bob: Una
curva :
Un divisor [ ]
Salida: La clave común [ ]
Paso 1.
Paso 2.
Paso 3.
Paso 4.
Paso 5.
44
4.3 LIBRERIAS USADAS PARA LA IMPLEMENTACIÓN EN LENGUAJE C 4.3.1 NTL Para el desarrollo del algoritmo de intercambio de clave, es necesaria la
posibilidad de operar eficientemente enteros de tamaño mucho mayor a los
convencionales (8, 16, 32 bits); debido a la seguridad del sistema, y estas se
realizan en un determinado campo finito, es por estas razones que se utiliza la
librería NTL.
NTL es una librería de alto desempeño que ofrece estructuración de datos y
algoritmos para el trabajo con enteros de longitud arbitraría, así como también
el manejo de polinomios en campos finitos, esta librería proporciona:
- Aritmética para enteros de longitud arbitraria
- Aritmética polinomial sobre enteros y campos finitos incluyendo
factorización de polinomios.
NTL ofrece las siguientes clases, o tipo de datos:
- ZZ: Enteros grandes
- ZZ_p: Enteros grandes en campo finito
- GF2: Enteros en campo finito
- ZZX: Polinomios sobre ZZ
- ZZ_pX: Polinomios sobre ZZ_p
- GF2X: Polinomios sobre
- ZZ_pE: Extensiones de campo sobre ZZ_p
- GF2E: Extensiones de campo sobre
- ZZ_pEX: Polinomios sobre ZZ_pE
- GF2EX: Polimonios sobre GF2E
Ejemplo:
Se requiere asignar 471605284963328985601374591564566265882887367819600103966
a una variable y 306880471515269672058113247244559505093054938574631821 a
45
una variable z, luego se desean sumar y guardar en una variable y, para ello se
procede de la siguiente manera:
1. Se inicializan las variables:
2. Mediante la función conv asigno el entero a la variable:
3. Se realiza la suma:
4.3.2 G2HEC Como se enunció anteriormente en la Sección 2.3.8 del segundo capítulo de
este documento, la operación más importante para el algoritmo de intercambio
de clave es la multiplicación escalar (ver Algoritmo 2), la cual tiene su base en
el algoritmo de Cantor (Algoritmo 1), en este algoritmo es necesario la
obtención de un divisor.
Para la obtención del divisor es necesario seleccionar una curva hiperelíptica
segura, de la forma:
Posteriormente se calculan los puntos que satisfagan la ecuación de la
curva, y a diferencia de las curvas elípticas, es necesaria la obtención del
jacobiano de la curva para poder realizar la operación de grupo. Luego
mediante el jacobiano de la curva se obtiene un divisor que será utilizado en los
Algoritmos 1 y 2. La librería G2HEC provee una amplia gama de funciones para
sistemas criptográficos que utilicen curvas de género 2, entre sus funciones
están:
46
- Generación de curvas hiperelípticas
- Operaciones del divisor de grupo en el jacobiano de la curva, tal como
son la suma y el doblado de un divisor, así como la multiplicación
escalar.
G2HEC trabaja básicamente con dos tipos de datos, field_t en la cual se define
el elemento delimitador del campo, y poly_t, en la cual se almacenan los
elementos del campo en representación polinomial, las clases utilizadas en
esta librería son g2hcurve en la cual se almacenan los dos polinomios
correspondientes de la curva hiperelíptica y y divisor, en la cual se
almacenan los polinomios [ ] los cuales son la presentación en
Mumford del divisor (ver Sección 2.3.5 del capítulo 2).
Las funciones utilizadas de la librería para este trabajo se presentan en la
Tabla 5:
Tabla 5: Funciones utilizadas de la librería G2HEC
FUNCIÓN DESCRIPCIÓN
Almacena en el coeficiente de
el valor de
Almacena el polinomio en el
polinomio de la curva
Almacena el polinomio en el
polinomio de la curva
Comprueba si la curva es válida
Retorna en el polinomio del
divisor
Retorna en el polinomio del
divisor
Almacena el polinomio en el
polinomio del divisor
47
Almacena el polinomio en el
polinomio del divisor
Realiza la multiplicación escalar de
[n]P y lo almacena en A
Realiza la suma mediante cantor
de P y N y lo almacena en A
Esta librería está basada en la librería descrita en la sección 4.3.1 de este
capítulo por lo que es necesario el trabajo conjunto de ambas.
48
5. IMPLEMENTACIÓN DEL SISTEMA CRIPTOGRAFICO BASADO EN CURVAS HIPERELIPTICAS Y TWOFISH
5.1 DESCRIPCIÓN GENERAL DEL SISTEMA El sistema criptográfico se compone de dos algoritmos, el primero de ellos
establecerá una clave común entre los dos participantes del proceso de
comunicación, una vez hecho esto, la clave común servirá para el segundo
algoritmo el cual estará encargado de cifrar la información que viajará por el
medio, en la Figura 10 se presenta el diagrama de bloques y punto de partida
para la implementación de este trabajo.
Figura 10: Diagrama de bloques del sistema criptográfico
Como se enuncio en la Sección 1.2 del primer capítulo, este proyecto hace
parte de un macro proyecto, y por lo tanto los bloques: Configuración, Inicio de
sesión y Fin de sesión, mostrados en la Figura 8, van a tener un tratamiento
especial debido a que no se tiene certeza de cuál será la manera en la que se
establecerá el lazo que comunicará los participantes del proceso, a
continuación se explica con mayor detalle cada uno de los bloques del proceso
general del sistema criptográfico.
Para mayor entendimiento vamos a llamar a los participantes del proceso como
Servidor y Ambulancia.
Configuracion
Inicio de sesión
Intercambio de clave: DHHECC
Cifrado de la información: TWOFISH
Fin de sesión
49
5.1.1 Configuración Servidor y Ambulancia deben tener una configuración inicial para luego
proceder con el siguiente bloque, esta configuración consisten en la selección
de un campo primo, una curva hiperelítica segura y un divisor del jacobiano de
la curva. Dichos parámetros pueden ser obtenidos de manera pública, es decir
que cualquier entidad, participante o no del proceso puede obtener dicha
información.
Para la implementación de este trabajo, se optó por utilizar un campo primo y
una curva hiperelíptica constantes en ambos participantes, y el parámetro que
varía en cada sesión, es el divisor del jacobiano de la curva, el cual es
calculado por Servidor, y posteriormente enviado hacia Ambulancia, de esta
manera ambos han concluido con la etapa de configuración.
La curva hipereíptica utilizada se generó mediante el uso de la librería G2HEC
descrita en la sección 4.3.2 del cuarto capítulo, y el numero primo mediante la
librería NTL de la sección 4.3.1 del mismo capítulo, dichos parámetros se
guardaron y se incluyeron de manera constante en el sistema criptográfico de
Servidor y Ambulancia.
La implementación del bloque de configuraciones se realizó de la siguiente
manera:
- Se definió el primo a utilizar en el campo, y se definieron los
coeficientes de los polinomios y que componen la curva
hiperelíptica (ver sección 2.3.1).
50
- Bloque de configuración para Servidor:
51
[ ] [ ] [ ] [ ] [ ]
- Bloque de configuración para Ambulancia:
52
5.1.2 Inicio de sesión Como se enunció anteriormente, no se tiene certeza de la tecnología que se
utilizará para la comunicación en el proyecto final del que hace parte este
trabajo, por ello se estableció el uso de RS232 para interconectar los
participantes del proceso, y así lograr él envió de información de extremo a
extremo.
El bloque Inicio de sesión se implementó mediante el envío de un carácter
desde Ambulancia a Servidor con el fin de comenzar el proceso de
comunicación. Se concluye que Servidor debe estar listo para recibir este
carácter en todo momento.
Figura 11: Diagrama de flujo para el inicio de sesión en Servidor
Figura 12: Diagrama de flujo para el inicio de sesión en Ambulancia
53
En las Figuras 11 y 12 se puede observar la utilizacion de una variable
denominada n, la utilizacion de esta se debe al uso de RS232, pues la funcion
RS232_PollComport retorna el numero extacto de bytes recibidos en el puerto,
como se muestra en el diagrama de flujo de la Figura 11, una vez ejecutado el
algoritmo de Ambulancia, se puede apreciar que después de la etapa de
inicializaciones (Configuración), se procede a enviar la confirmación de inicio
de sesión, y se envía un carácter correspondiente a 8 bits, es decir un byte.
La implementación de la función de confirmación ( enviará un
byte mediante la función , así Ambulancia le informa a Servidor
de que ha iniciado sesión y está listo para recibir el divisor, una vez recibido, se
está listo para proceder con el bloque Intercambio de clave.
La función se implementó de la siguiente manera:
5.1.3 Intercambio de clave Una vez que las entidades Ambulancia y Servidor han acordado con el campo
finito, la curva hiperelíptica y el divisor del jacobiano de la curva, se está listo
para realizar el algoritmo de intercambio de claves Diffie-Hellman para curvas
54
hiperelípticas (ver sección 4.2.2), cabe resaltar que Ambulancia y Servidor
necesitan maneras distintas de implementar este algoritmo debido a la
sincronización de la comunicación. Para la implementación de este algoritmo
se muestra en la Figura 13 el diagrama de flujo realizado para Servidor, y en la
Figura 14 el realizado para Ambulancia.
Figura 13: Diagrama de flujo para
intercambio de clave en Servidor
Figura 14: Diagrama de flujo para
intercambio de clave en Ambulancia
55
5.1.4 Cifrado de la información y fin de sesión En este bloque, Servidor encripta el mensaje por medio del algoritmo
TWOFISH utilizando la clave acordada en el bloque anterior, y lo envía hacia
Ambulancia, posteriormente Ambulancia realiza la desencriptación y obtiene el
mensaje requerido. Una vez hecho esto Servidor y Ambulancia, utilizando la
función de confirmación ( ) descrita en la sección 5.1.2 de este
capítulo, finalizan la sesión mediante él envió del carácter correspondiente. El
Flujo correspondiente para las etapas de cifrado y descifrado se describen en
las Figuras 3 y 9.
56
6. PRUEBAS Y RESULTADOS En este capítulo se mostraran una serie de pruebas realizadas a las
operaciones implementadas para el intercambio de clave entre los
participantes, así como a las implementadas para el algoritmo de encriptación y
desencriptación, con el fin de simular el ambiente de trabajo real del sistema
criptográfico, se realizaron las pruebas de funcionamiento en dos herramientas
distintas, una de ellas es un computador personal con sistema operativo
Windows, la otra es un computador de placa reducida denominado
Raspberry Pi con sistema operativo Debían basado en Unix.
Figura 15: Foto real del sistema
A continuación en la Tabla 6 se presentan las características de dichas
herramientas.
Tabla 6: Especificaciones técnicas de herramientas usadas para pruebas
Computador Raspberry Pi Modelo B 2011
Procesador AMD E-350 ARM1176JZF-S
Frecuencia reloj 1,6 GHz 700 MHz
Memoria RAM 2 Gb 256 MB
Sistema Operativo Windows 7 Debian (Unix)
57
5.1 INTERCAMBIO DE CLAVE Para la realización de las pruebas en el computador y en la Raspberry Pi se
procedió a obtener los valores ofrecidos en segundos por la consola al ejecutar
y finalizar el programa, estos valores se recopilaron y se calcularon valores
promedio para tener una certeza en la medida.
5.1.1 Suma y Doblado de divisores
Las pruebas aplicadas al algoritmo de Cantor se realizaron mediante la toma
de datos de los valores de tiempo que se presentaban antes de la operación y
el tiempo después de la operación, se tomaron muestras de 10 valores y se
calculó el promedio, dando como resultado un promedio de 38 ms en el
computador y un valor de 1.365 ms en la Raspberry Pi, teniendo en cuenta que
se están utilizando curvas genero 2 y un campo finito [ ] en el cual el
parámetro es un entero primo de 192 bits. A continuación en la Tabla 7 y 8 se
presentan los resultados obtenidos.
Tabla 7: Tiempos medidos en el algoritmo de Cantor en el Computador
Antes de Cantor
Después de Cantor
Tiempo de Cantor (Segundos)
0,13 0,2 0,07
0,09 0,16 0,07
0,05 0,09 0,04
0,07 0,09 0,02
0,06 0,07 0,01
0,1 0,16 0,06
0,06 0,1 0,04
0,06 0,09 0,03
0,07 0,08 0,01
0,09 0,12 0,03
Promedio 0,078 0,116 0,038
58
Tabla 8: Tiempos medidos en el algoritmo de Cantor en la Raspberry Pi
Antes de Cantor Después de cantor Tiempo de Cantor (Segundos)
0,449 0,885 1,334
0,552 0,812 1,364
0,512 0,845 1,357
0,445 0,877 1,322
0,578 0,756 1,334
0,521 0,875 1,396
0,498 0,965 1,463
0,412 0,984 1,396
0,445 0,856 1,301
0,502 0,887 1,389
Promedio 0,4914 0,8742 1,3656
5.1.2 Multiplicación escalar Las pruebas aplicadas al método de Multiplicación Escalar de Montgomery se
realizaron mediante la toma de datos de los valores de tiempo que se
presentaban antes de la operación y el tiempo después de la operación, se
tomaron muestras de 10 valores y se calculó el promedio, dando como
resultado un promedio de 299 ms en el computador y un promedio de 3,626 ms
en la Raspberry Pi, teniendo en cuenta que se están utilizando curvas genero 2
y un campo finito [ ] en el cual el parámetro es un entero primo de 192
bits. A continuación en la Tabla 9 y 10 se presentan los resultados obtenidos.
Tabla 9: Tiempos medidos en el método de Multiplicación Escalar de
Montgomery en el computador
Antes de SM Después de SM Tiempo de SM (Segundos)
0,11 0,35 0,24
0,1 0,36 0,26
0,07 0,39 0,32
0,07 0,45 0,38
0,08 0,38 0,3
0,11 0,42 0,31
0,12 0,35 0,23
0,05 0,41 0,36
0,12 0,4 0,28
0,07 0,38 0,31
Promedio 0,09 0,389 0,299
59
5.2 ENCRIPTACIÓN Y DESENCRIPTACIÓN Para las pruebas realizadas en el algoritmo TWOFISH se procedió de igual
manera a la planteada en los algoritmos de Cantor y Montgomery, cabe resaltar
que los tiempos de encriptación y desencriptacion tienen un costo igual debido
a que la desencriptacion es el proceso inverso de la encriptación. A
continuación se presentan en la Tabla 11 y 12 los resultados obtenidos en
tiempo para las dos herramientas utilizadas.
Tabla 10: Tiempos medidos en el método de Multiplicación Escalar de
Montgomery en la Raspberry Pi
Antes de MS Después de MS Tiempo de MS (Segundos)
0,42 3,075 3,495
0,521 3,515 4,036
0,496 3,206 3,702
0,522 2,919 3,441
0,451 3,415 3,866
0,487 3,438 3,925
0,469 2,954 3,423
0,441 2,971 3,412
0,436 2,833 3,269
0,521 3,179 3,7
Promedio 0,4764 3,1505 3,6269
Tabla 11: Tiempos medidos en la
encriptación en el computador
Tabla 12: Tiempos medidos en la
encriptación en la Raspberry Pi
TWOFISH 16 bits
0,09
0,085
0,098
0,08
0,08
0,092
0,081
0,089
0,084
0,094
Promedio 0,0873
TWOFISH 16 bits
0,103
0,101
0,106
0,116
0,133
0,131
0,135
0,123
0,114
0,123
Promedio 0,1185
60
5.3 COMPARACIÓN CON OTRAS IMPLEMENTACIONES
En la bibliografía investigada se encuentran implementaciones tanto para
TWHOFISH como para los algoritmos de multiplicación escalar y suma de
divisores, dichas implementaciones se relacionan en las siguientes tablas,
teniendo en cuenta que las especificaciones de las otras implementaciones son
considerablemente diferentes a las obtenidas en los equipos en que se
realizaron las pruebas de este trabajo.
Tabla 13: Comparación con otras implementaciones para la encriptación
usando algoritmo TOWFISH
Procesador Lenguaje Tiempo Encriptación (ms)
Schneier, B. et al 1998 Intel II C 9,3
Gehlot, P. et al 2013 Intel Core i3 VHDL 0,105
Cortes, C. 2016 AMD E-350 C 8,7
Cortes, C. 2016 ARM1176JZF-S C 11,8
Tabla 14: Comparación con otras implementaciones para Multiplicación escalar
en curvas hiperelípticas
Procesador Lenguaje Tiempo Multiplicación Escalar (s)
Ferrer, F. 2007 - Magma 10,23
Lange, T. 2003 Intel IV C 5,37
Cortes, C. 2016 AMD E-350 C 0,299
Cortes, C. 2016 ARM1176JZF-S C 3,62
Tabla 15: Comparación con otras implementaciones para la suma y doblado de
divisores en curvas hiperelíticas
Procesador Lenguaje Tiempo Suma y Doblado (s)
Ferrer, F. 2007 - Magma 6,21
Lange, T. 2003 Intel IV C 3,18
Cortes, C. 2016 AMD E-350 C 0,038
Cortes, C. 2016 ARM1176JZF-S C 1,36
61
7. CONCLUSIONES Y TRABAJO FUTURO
7.1 CONCLUSIONES Este trabajo presenta la implementación de un sistema criptográfico que utiliza
una curva hiperelíptica de genero 2 trabajando en un campo finito [ ]; donde
q es un numero primo de 192 bits, utiliza el algoritmo de Cantor para la suma y
doblado de divisores y el método de Multiplicación Escalar Montgomery para
realizar el computo de un numero entero por un divisor, todo esto con el fin de
realizar el algoritmo de intercambio de claves Diffie-Hellman en su versión para
curvas hiperelípticas (DHHEC). El sistema utiliza también un cifrador de bloque
de 128 bits denominado TWOFISH para la encriptación y desencriptación de la
información, la clave de este algoritmo resulta de seleccionar los 128 bits
menos significativos de la clave acordada de 192 bits.
El sistema criptográfico se diseñó y se implementó en lenguaje C utilizando la
librería libg2hec para las operaciones a realizar en la curva utilizada, y la
librería NTL de manera conjunta con GMP para la generación de números
primos y operaciones con números de 192 bits de longitud. La compilación y
pruebas se desarrollaron en un computador personal y una Raspberry Pi
modelo B 2011.
El tiempo observado en el computador para la multiplicación escalar fue de 299
ms, este mismo tiempo se midió en la Raspberry Pi en la cual arrojo un valor
de 3.626 ms. Para el algoritmo TWOFISH el tiempo estimado de encriptación
fue de 0,087 ms para el computador y el tiempo que se obtuvo en la Raspberry
Pi fue de 0,118 ms.
Observando las respuestas en tiempo del sistema, se puede concluir que con
una oportuna tecnología de comunicación, los algoritmos realizados en este
trabajo desarrollaran sus funciones de manera óptima.
62
7.2 TRABAJO FUTURO Durante la implementación de este trabajo se tuvo en cuenta el diseño del
algoritmo global que permitiera la transferencia de archivos encriptados desde
un servidor a una ambulancia, como lo enuncia el macro proyecto del que hace
parte este trabajo, a su vez, y por necesidad del proseguir con el desarrollo de
este proyecto, no se tuvo en cuenta la tecnología utilizada para la
comunicación de estos dos entes, y se optó por elegir RS232 con el fin de
realizar las pruebas, es por esto que nace la necesidad de re implementar las
funciones de envió y recibo de datos una vez se tenga seleccionada la
tecnología de comunicación en el macro proyecto final.
Se considera apropiado complementar este sistema criptográfico utilizando
funciones de firma digital lo cual aumentaría la seguridad de este, así como la
confiabilidad de los datos. También es necesaria la implementación de nuevos
algoritmos que permitan obtener la información requerida en los servidores a
utilizar, pues para la realización de las pruebas de este proyecto, el archivo
encriptado se encontraba dentro de la misma carpeta del programa.
Para finalizar, como trabajo futuro se propone un nuevo trabajo de grado el cual
tenga como finalidad el acople del sistema criptográfico y los equipos finales a
utilizar en el macro proyecto final, cabe resaltar que ya existe un sistema
embebido realizado por estudiantes de la Universidad de San Buenaventura el
cual pretende ser el utilizado en la ambulancia, así pues existiría la necesidad
de seleccionar el servidor y así realizar el acople de software y hardware que
permitirán mejorar los procesos de comunicación que se requieren al momento
de atender un paciente en una ambulancia.
63
8. BIBLIOGRAFIA
Abdalla, M., Bellare, M., & Rogaway, P. (1999). DHAES: An Encryption Scheme
Based on the Diffie-Hellman Problem. IEEE P1363a Submission.
Avanzi, R. (2006). Generic Algorithms for Computing Discrete Logarithms. En R. Avanzi, C. Doche, T. Lange, K. Nguyen, & F. Vercauteren, Handbook of Elliptic and Hyperelliptic Curve Cryptography (págs. 475-209). Boca Raton: Chapman & Hall / CRC.
Bellare, M., Desai, A., Jokipii, E., & Rogaway, P. (1997, October). A concrete
security treatment of symmetric encryption. In Foundations of Computer Science, 1997. Proceedings., 38th Annual Symposium on (pp. 394-403). IEEE.
Benevuto, C. (31 de mayo de 2012). Galois field in cryptography. Springer
Berlin Heidelberg. Bogdanov, A., Khovratovich, D., & Rechberger, C. (2011). Biclique
cryptanalysis of the full AES. In Advances in Cryptology–ASIACRYPT 2011(pp. 344-371). Springer Berlin Heidelberg.
Cantor, D. G. (1987). Computing in the Jacobian of a Hyperelliptic Curve.
Mathematics of Computation , 48 (177), 95-101.
Daemen, J., & Rijmen, V. (2002). The design of Rijndael: AES-the advanced encryption standard. Springer Science & Business Media.
Diffie, W., & Hellman, M. (1976). New directions in cryptography. IEEE
transactions on Information Theory, 22(6), 644-654.
Duquesne, S., & Lange, T. (2006). Arithmetic of Hyperelliptic Curves. En H. Cohen, G. Frey, R. Avanzi, C. Doche, T. Lange, K. Nguyen, y otros, Handbook of Elliptic and Hiperelliptic Curve Cryprography (págs. 303-353). Boca Raton: Chapman &Hall/CRC.
Duquesne, S. (2007). Traces of the Group Law on the Kummer Surface of a
Curve of Genus 2 in Characteristic 2. Preprint .
Elminaam, D. S. A., Abdual-Kader, H. M., & Hadhoud, M. M. (2010). Evaluating The Performance of Symmetric Encryption Algorithms. IJ Network Security, 10(3), 216-222.
Fujisaki, E., & Okamoto, T. (1999, August). Secure integration of asymmetric
and symmetric encryption schemes. In Annual International Cryptology
Conference (pp. 537-554). Springer Berlin Heidelberg.
64
Frey, G., & Lange, T. (2006). Background on Curves and Jacobians. En H.
Cohen, G. Frey, R. Avanzi, C. Doche, T. Lange, K. Nguyen, y otros,
Handbook Of Elliptic And Hiperelliptic Curve Cryprography (págs. 45-85).
Boca Raton: Chapman &Hall/CRC.
Fúster, A., de la Guía, D., Hernandez, L., Montoya, F., & Muñoz, J. (2001).
Técnicas criptográficas de protección de datos. México.
Gaudry, P. (2000). An Algorithm for Solving the Discrete Log Problem on
Hyperelliptic Curves. Advances in Cryptology - EUROCRYPT 2000,
1807, 19-34.
Gura, N., Patel, A., Wander, A., Eberle, H., & Shantz, S. C. (2004). Comparing elliptic curve cryptography and RSA on 8-bit CPUs. In Cryptographic Hardware and Embedded Systems-CHES 2004 (pp. 119-132). Springer Berlin Heidelberg.
Hankerson, D., Menezes, A., & Vanstone, S. (2004). Elliptic Curve Arihtmetic.
En D. Hankerson, A. Menezes, & S. Vanstone, Guide to Elliptic Curve Criptography (págs. 75-152). New York: Springer.
IEEE 1363a-2004. (2004). Standard Specifications for Public Key Cryptography
- Amendment 1: Additional Techniques.
Kapoor, V., Abraham, V. S., & Singh, R. (2008). Elliptic curve cryptography.ACM Ubiquity, 9(20), 20-26.
Koblitz, N. (1987). Elliptic curve cryptosystems. Mathematics of
computation,48(177), 203-209. Koblitz, N. (1989). Hyperelliptic cryptosystems. Journal of cryptology, 1(3), 139-
150. Kumar, N., Kaur, K., Misra, S. C., & Iqbal, R. (2015). An intelligent RFID-
enabled authentication scheme for healthcare applications in vehicular mobile cloud. Peer-to-Peer Networking and Applications, 1-17.
Lange, T. (2002). Efficient Arithmetic on genus 2 Hyperelliptic Curves over
Finite Fields via Explicit Formulae. Cryptology ePrint Archive (121).
Lange, T. (2005). Formulae for Arithmetic on Genus 2 Hyperelliptic Curves. Applicable Algebra in Engineering, Communication and Computing, 15 (5), 295-328.
Lopez, J., & Dahab, R. (2000). An overview of elliptic curve cryptography. Menezes, A. J.; WU, Y.-H. & zuccherato,R. J. (1996). An Elementary
Introduction to Hyperelliptic Curves. En: N. Koblitz, Algebraic Aspects of Cryptography (págs.
155-178). Springer.
65
Menezes, A., Oorschot, P. V., & Vanstone, S. (1997). Handbook of Applied
Cryptography. Boca Raton: CRC Press. Miller, V. (1986). Use of elliptic curves in cryptography. In Advances in
Cryptology—CRYPTO’85 Proceedings (pp. 417-426). Springer Berlin/Heidelberg.
García, O. C. (2010). Revisión de la aritmética de curvas hiperelípticas para la
implementación de un criptoprocesador a usarse en un sistema
HECC. Revista Guillermo de Ockham, 8(2).
Prabu, M., & Shanmugalakshmi, R. (2010, February). A study of elliptic curve
cryptography and its application. In Proceedings of the International Conference and Workshop on Emerging Trends in Technology (pp. 425-427). ACM.
Quisquater, J. J., & Couvreur, C. (1982). Fast decipherment algorithm for RSA
public-key cryptosystem. Electronics letters, 18(21), 905-907.0 Schneier, B., Kelsey, J., Whiting, D., Wagner, D., Hall, C., & Ferguson, N.
(1998). Twofish: A 128-bit block cipher. NIST AES Proposal, 15.
Sudha, G., & Ganesan, R. (2013, April). Secure transmission medical data for
pervasive healthcare system using android. In Communications and Signal Processing (ICCSP), 2013 International Conference on (pp. 433-436). IEEE.
Sugawara, T., Hayashi, Y. I., Homma, N., Mizuki, T., Aoki, T., Sone, H., &
Satoh, A. (2009, July). Spectrum analysis on cryptographic modules to counteract side-channel attacks. In EMC (Vol. 9, pp. 21-24).
Wollinger, T. (2001). Computer Architectures for Cryptosystems Based on
Hyperelliptic Curves. Worchester, New York: Master Thesis, Worchester Polytechnic Institute.
Xiangyu, J., & Chao, W. (2005, August). The application of elliptic curve
cryptosystem in wireless communication. In Microwave, Antenna, Propagation and EMC Technologies for Wireless Communications, 2005. MAPE 2005. IEEE International Symposium on (Vol. 2, pp. 1602-1605). IEEE.
Yokoyama, V. T. V. (2000). Elliptic curve cryptosystem. Fujitsu Sci. Tech. J,36(2), 140-146.
Yoneda, M. (1996). U.S. Patent No. 5,517,509. Washington, DC: U.S. Patent and Trademark Office.
66
ANEXOS
ANEXO 1: CODIGO PRINCIPAL SERVIDOR
int main()
{
//Verifica la disponibilidad del puerto
if(RS232_OpenComport(cport_nr, bdrate, mode))
{
printf("Can not open comport\n");
return(0);
}
//con la libreria time.h obtengo el segundo en que se
//ejecuta el programa
int sem=time(0);
//semilla para random
SetSeed(conv<ZZ>(sem));
// inicializo el campo primo GF(p):
ZZ p = to_ZZ(ps);
field_t::init(p);
//inicializo las variables ZZ_p con el modulo
ZZ_p::init(p);
//polinomios utiles para crear la curva y divisores
poly_t h,f,u,v,temp;
//Divisores
divisor P,Q1,Q2,K;
//defino la curva de tipo g2hcurve
g2hcurve curve;
//creo la clave secreta de A
ZZ a;
RandomBnd(a,p);
//seteo los coeficientes del polinomio h
SetCoeff(h,0,str_to_ZZ_p(h0));
SetCoeff(h,1,str_to_ZZ_p(h1));
SetCoeff(h,2,str_to_ZZ_p(h2));
//seteo los coeficientes del polinomio f
SetCoeff(f,0,str_to_ZZ_p(f0));
SetCoeff(f,1,str_to_ZZ_p(f1));
SetCoeff(f,2,str_to_ZZ_p(f2));
SetCoeff(f,3,str_to_ZZ_p(f3));
SetCoeff(f,4,str_to_ZZ_p(f4));
SetCoeff(f,5,str_to_ZZ_p(f5));
//asigno los polinomios a la curva y actualizo los parametros
curve.set_h(h);
curve.set_f(f);
67
curve.update();
//asigno un divisor a la curva
P.set_curve(curve);
//Escojo un divisor randomico
P.random();
//obtengo los polinomios u y v del divisor (mumford
representation)
u = P.get_upoly();
v = P.get_vpoly();
SetCoeff(temp,0,to_ZZ_p(conv<ZZ>(u[0])));
SetCoeff(temp,1,to_ZZ_p(conv<ZZ>(u[1])));
SetCoeff(temp,2,to_ZZ_p(conv<ZZ>(u[2])));
SetCoeff(temp,3,to_ZZ_p(conv<ZZ>(v[0])));
SetCoeff(temp,4,to_ZZ_p(conv<ZZ>(v[1])));
FILE * fp;
const char * tempo;
fp = fopen ("Divisor.txt", "a+");
for(j=0;j<(deg(temp)+1);j++){
str = zToString(conv<ZZ>(temp[j]));
str[str.size()]= 'z';
siz=siz + str[str.size()];
tempo = str.c_str();
for(i=0;i<strlen(tempo)+1;i++){
if(tempo[i] == 'z'){
fprintf(fp, "z");
i=strlen(tempo);
}
if(tempo[i] > 0){
fprintf(fp, "%i",tempo[i]-48);
}else fprintf(fp, "%i",tempo[i]);
}
str.clear();
}
fclose(fp);
while(1){
//pregunta si hay datos de confirmacion en el buffer
n = RS232_PollComport(cport_nr, buf, 4095);
if(n == 1){
//Guardo el valor de confirmacion en la variable flag
flag = (buf[0]-48);
}
if(flag==1){
//A envia el divisor de la curva a B
SendDivisor(0);
}
if(flag==2){
//Necesidad de contador para que lo haga una sola vez
68
if(cont==0){
//Envio la confirmacion a B de que esta listo
para recibir Q2
Confirmation(2);
cont++;
}
//Se obtiene el divisor Q2 proveniente de B; Q2=b*P
Q2 = GetDivisor();
if(flag==0){
//A realiza multiplicacion escalar de a con P
para su clave privada
ML(Q1,P,a);
//obtengo los polinomios u y v del divisor Q1
u = Q1.get_upoly();
v = Q1.get_vpoly();
SetCoeff(temp,0,to_ZZ_p(conv<ZZ>(u[0])));
SetCoeff(temp,1,to_ZZ_p(conv<ZZ>(u[1])));
SetCoeff(temp,2,to_ZZ_p(conv<ZZ>(u[2])));
SetCoeff(temp,3,to_ZZ_p(conv<ZZ>(v[0])));
SetCoeff(temp,4,to_ZZ_p(conv<ZZ>(v[1])));
//Crea el archivo
FILE * fq;
fq = fopen ("DivisorQ1.txt", "a+");
for(j=0;j<(deg(temp)+1);j++){
str = zToString(conv<ZZ>(temp[j]));
str[str.size()]= 'z';
siz1=siz1 + str[str.size()];
tempo = str.c_str();
for(i=0;i<strlen(tempo)+1;i++){
if(tempo[i] == 'z'){
fprintf(fq, "z");
i=strlen(tempo);
}
if(tempo[i] > 0){
fprintf(fq, "%i",tempo[i]-48);
}else {
fprintf(fq, "%i",tempo[i]);
}
}
str.clear();
}
fclose(fq);
//Envio la confirmacion a B de que esta listo
para enviar Q1
Confirmation(3);
cont=0;
}
}
if(flag==3){
//A envia el divisor de la curva a B
SendDivisor(1);
//Ya puedo calcular la clave comun
ML(K,Q2,a);
69
u = K.get_upoly();
str = zToString(conv<ZZ>(u[0]));
tempo = str.c_str();
FILE * fc;
fc = fopen("clave.txt","w+");
fprintf(fc, "%s", tempo);
fclose(fc);
fc = fopen("clave.txt","r");
fgets((char*)clave, 16, fc);
fclose(fc);
//remove("clave.txt");
//printf("\nClave: %s\n",clave);
}
if(flag==4){
//Necesidad de contador para que lo haga una sola vez
if(cont==0){
//Envio la confirmacion a B de que esta listo
para comunicacion
Confirmation(4);
cont++;
}
//printf("\nListo para comunicacion\n");
SendHCL();
remove("clave.txt");
remove("Divisor.txt");
remove("DivisorQ1.txt");
return(0);
}
}
}
70
ANEXO 2: CODIGO PRINCIPAL AMBULANCIA
int main()
{
const char * tempo;
//Verifica la disponibilidad del puerto
if(RS232_OpenComport(cport_nr, bdrate, mode))
{
printf("Can not open comport\n");
return(0);
}
//con la libreria time.h obtengo el segundo en que se
//ejecuta el programa
int sem=time(0);
//semilla para random
SetSeed(conv<ZZ>(sem));
// inicializo el campo primo GF(p):
ZZ p = to_ZZ(ps);
field_t::init(p);
//inicializo las variables ZZ_p con el modulo
ZZ_p::init(p);
//polinomios utiles para crear la curva y divisores
poly_t h,f,u,v,temp;
//Divisores
divisor P,Q1,Q2,K;
//defino la curva de tipo g2hcurve
g2hcurve curve;
//creo la clave secreta de A
ZZ b;
RandomBnd(b,p);
RandomBnd(b,p);
//seteo los coeficientes del polinomio h
SetCoeff(h,0,str_to_ZZ_p(h0));
SetCoeff(h,1,str_to_ZZ_p(h1));
SetCoeff(h,2,str_to_ZZ_p(h2));
//seteo los coeficientes del polinomio f
SetCoeff(f,0,str_to_ZZ_p(f0));
SetCoeff(f,1,str_to_ZZ_p(f1));
SetCoeff(f,2,str_to_ZZ_p(f2));
SetCoeff(f,3,str_to_ZZ_p(f3));
SetCoeff(f,4,str_to_ZZ_p(f4));
SetCoeff(f,5,str_to_ZZ_p(f5));
//asigno los polinomios a la curva y actualizo los parametros
curve.set_h(h);
curve.set_f(f);
curve.update();
//asigno un divisor a la curva
71
P.set_curve(curve);
Confirmation(1);
fw = fopen("HCL.txt","w");
while(1){
//printf("\n%i\n",flag);
//pregunta si hay datos de confirmacion en el buffer
n = RS232_PollComport(cport_nr, buf, 4095);
if(n == 1){
//Guardo el valor de confirmacion en la variable flag
flag = (buf[0]-48);
//for(i=0;i<strlen((char*)buf);i++)buf[i]=0;
}
if(flag==1){
P = GetDivisor();
if(flag==0){
//B realiza multiplicacion escalar de b con P
para su clave privada
ML(Q1,P,b);
//obtengo los polinomios u y v del divisor Q1
u = Q1.get_upoly();
v = Q1.get_vpoly();
SetCoeff(temp,0,to_ZZ_p(conv<ZZ>(u[0])));
SetCoeff(temp,1,to_ZZ_p(conv<ZZ>(u[1])));
SetCoeff(temp,2,to_ZZ_p(conv<ZZ>(u[2])));
SetCoeff(temp,3,to_ZZ_p(conv<ZZ>(v[0])));
SetCoeff(temp,4,to_ZZ_p(conv<ZZ>(v[1])));
//Crea el archivo
FILE * fp;
fp = fopen ("DivisorQ1.txt","a+");
for(j=0;j<(deg(temp)+1);j++){
str = zToString(conv<ZZ>(temp[j]));
str[str.size()]='z';
siz = siz + str[str.size()];
tempo = str.c_str();
for(i=0;i<strlen(tempo)+1;i++){
if(tempo[i] == 'z'){
fprintf(fp, "z");
i=strlen(tempo);
}
if(tempo[i] > 0){
fprintf(fp, "%i", tempo[i]-48);
}else fprintf(fp, "%i",tempo[i]);
}
str.clear();
}
fclose(fp);
//Envio la confirmacion a B de que esta listo
para enviar Q1
Confirmation(2);
cont=0;
}
72
}
if(flag==2){
//A envia el divisor de la curva a B
SendDivisor();
}
if(flag==3){
//Necesidad de contador para que lo haga una sola vez
if(cont==0){
//Envio la confirmacion a B de que esta listo
para recibir Q2
Confirmation(3);
cont++;
}
//Se obtiene el divisor Q2 proveniente de A; Q2=a*P
Q2 = GetDivisor();
if(flag==0){
//Ya puedo calcular la clave comun
ML(K,Q2,b);
u = K.get_upoly();
str = zToString(conv<ZZ>(u[0]));
tempo = str.c_str();
FILE * fc;
fc = fopen ("clave.txt","w+");
fprintf(fc, "%s", tempo);
fclose(fc);
fc = fopen("clave.txt","r");
fgets ((char*)clave, 16, fc);
fclose(fc);
//printf("\nClave: %s\n",clave);
//Envio la confirmacion a A de que esta listo
para comunicacion
Confirmation(4);
cont=0;
}
}
if(flag==4){
//printf("\nListo para comunicacion\n");
ReceiveHCL();
}
if(flag==5){
//printf("\nListo para comunicacion\n");
remove("clave.txt");
remove("DivisorQ1.txt");
return(0);
}
}
}
73
ANEXO 3: FUNCIONES IMPLEMENTADAS EN SERVIDOR Y AMBULANCIA
std::string zToString(const ZZ &z) {
std::stringstream buffer;
buffer << z;
return buffer.str();
}
void SendDivisor(){
FILE * fp;
char Gxx[500]="";
fp = fopen ("DivisorQ1.txt" , "r");
if (fp == NULL) perror ("Error opening file");
else {
if ( fgets (Gxx , siz , fp) != NULL ){
//puts (Gxx);
}
fclose (fp);
//remove("DivisorQ1.txt");
}
Gxx[strlen(Gxx)] = 'x';
//printf("\n%s\n",Gxx);
//En este for se envia el divisor que calculo A al receptor B
for(i=0;i<strlen(Gxx);i++) RS232_SendByte(cport_nr, Gxx[i]);
flag=0;
}
void Confirmation(int a){
switch(a){
case 1:
RS232_SendByte(cport_nr,'1');
break;
case 2:
RS232_SendByte(cport_nr,'2');
break;
case 3:
RS232_SendByte(cport_nr,'3');
break;
case 4:
RS232_SendByte(cport_nr,'4');
break;
default:
printf("\nError\n");
break;
}
}
divisor GetDivisor(){
divisor Q2;
poly_t u,v;
int i,cont2,cont1;
char u0temp[300]="";
char u1temp[300]="";
char u2temp[300]="";
char v0temp[300]="";
char v1temp[300]="";
74
if(n > 1){
cont2=0;
for(i=re; i<(re+n); i++){
poly[i] = buf[cont2];
cont2++;
}
re = re + n;
n = 0;
}
if(poly[re-1]=='x'){
//printf("\n%s\n",buf);
flag=0;
poly[re-1]=0;
cont1=0;
cont2=0;
for(i=0;i<strlen(poly);i++){
//delimita donde voy a guardar los
valores
//los valores terminan en z
if(poly[i]=='z'){
cont1++;
cont2=0;
}
if(cont1==0 && poly[i]!='z'){
u0temp[cont2]=poly[i];
cont2++;
}
if(cont1==1 && poly[i]!='z'){
u1temp[cont2]=poly[i];
cont2++;
}
if(cont1==2 && poly[i]!='z'){
u2temp[cont2]=poly[i];
cont2++;
}
if(cont1==3 && poly[i]!='z'){
v0temp[cont2]=poly[i];
cont2++;
}
if(cont1==4 && poly[i]!='z'){
v1temp[cont2]=poly[i];
cont2++;
}
}
//seteo los coeficientes del poly u y v
del divisor que llego de B
SetCoeff(u,0,str_to_ZZ_p(u0temp));
SetCoeff(u,1,str_to_ZZ_p(u1temp));
SetCoeff(u,2,str_to_ZZ_p(u2temp));
SetCoeff(v,0,str_to_ZZ_p(v0temp));
SetCoeff(v,1,str_to_ZZ_p(v1temp));
//clareo poly
for(i=0;i<strlen(poly);i++)poly[i]=0;
75
//seteo los coeficientes al divisor y
actualizo
Q2.set_upoly(u);
Q2.set_vpoly(v);
Q2.update();
cont2=0;
cont1=0;
re=0;
return Q2;
}
#ifdef _WIN32
Sleep(100);
#else
usleep(1000000); /* sleep for 100 milliSeconds */
#endif
}
void ReceiveHCL(){
int cont2;
if(n > 1){
cont2=0;
for(i=re; i<(re+n); i++){
ciphertext[i] = buf[cont2];
cont2++;
}
re = re + n;
}
if(ciphertext[re-1]==0xcc){
ciphertext[re-1]=0;
tam= (re-1);
paq= tam / 16;
res= tam % 16;
if(res > 0) paq = paq + 1;
for(i=1; i<=paq; i++){
for(j=0; j<16; j++){
paquetes[i][j] = ciphertext[j];
}
for(w=0; w<16;
w++)ciphertext[w]=ciphertext[(16*i)+w];
}
for(i=1; i<=paq; i++){
for(j=0; j<16; j++){
cifrado[j]= paquetes[i][j];
}
76
desencriptar(texto, cifrado, clave);
for(w=0;w<strlen((char*)texto);w++)fputc(texto[w],
fw);
for(j=0; j<16; j++){
cifrado[j]=0;
texto[j]=0;
}
}
fclose(fw);
flag=5;
}
#ifdef _WIN32
Sleep(100);
#else
usleep(100000); /* sleep for 100 milliSeconds */
#endif
}
77
ANEXO 4: IMPLEMENTACIÓN TWOFISH
unsigned int phta(unsigned int a, unsigned int b);
unsigned int phtb(unsigned int a, unsigned int b);
unsigned char permutacionq0(unsigned char in);
unsigned char permutacionq1(unsigned char in);
unsigned char mds (unsigned char a, unsigned char b);
unsigned int funcionh(unsigned char i, unsigned int m1, unsigned int
m2);
unsigned int funcionf(unsigned int i, unsigned int s0, unsigned int
s1);
unsigned int generarclaves(unsigned char i,unsigned char clave[]);
unsigned char mult(unsigned char a, unsigned char b);
unsigned int subclavesi(unsigned char clave[]);
unsigned int ronda(unsigned int r,unsigned int aa, unsigned int bb,
unsigned int cc, unsigned int dd);
unsigned int rondades(unsigned int r,unsigned int aa, unsigned int bb,
unsigned int cc, unsigned int dd);
unsigned int desencriptar(unsigned char texto[], unsigned char
cifrado[], unsigned char clave[]);
unsigned int encriptar(unsigned char texto[], unsigned char cifrado[],
unsigned char clave[]);
/*
+*********************************************************************
********
*
* Function Name: phta
*
* Function: realiza la suma modulo 32 de dos numeros
*
* Arguments: int a, int b;
* Return: int c
*
* Notes: resultado de una or entre los dos argumentos de entrada
*
-
**********************************************************************
******/
unsigned int phta(unsigned int a, unsigned int b){
unsigned int out;
out= (a + b);
return out;
78
}
/*
+*********************************************************************
********
*
* Function Name: phtb
*
* Function: realiza la suma modulo 32 de dos numeros
*
* Arguments: int a, int b;
* Return: int c
*
* Notes: resultado de una or entre los dos argumentos de entrada
*
-
**********************************************************************
******/
unsigned int phtb(unsigned int a, unsigned int b){
unsigned int out;
out= (a + (b<<1));
return out;
}
/*
+*********************************************************************
********
*
* Function Name: permutacionq0
*
* Function: realiza el calculo de la caja q0
*
* Arguments: char in
* Return: char out
*
* Notes: Esta funcion calcula el valor de q0
*
-
**********************************************************************
******/
unsigned char permutacionq0(unsigned char in){
unsigned char t0,t1,t2,t3,j;
unsigned char a,b,rot,des,out;
a=((in & 0xF0)>>4);
b=(in & 0x0F);
t0= a ^ b;
switch ( t0 ) {
case 0:
t0=0x08;
break;
79
case 1:
t0=0x01;
break;
case 2:
t0=0x07;
break;
case 3:
t0=0x0D;
break;
case 4:
t0=0x06;
break;
case 5:
t0=0x0F;
break;
case 6:
t0=0x03;
break;
case 7:
t0=0x02;
break;
case 8:
t0=0x00;
break;
case 9:
t0=0x0B;
break;
case 10:
t0=0x05;
break;
case 11:
t0=0x09;
break;
case 12:
t0=0x0E;
break;
case 13:
t0=0x0C;
break;
case 14:
t0=0x0A;
break;
case 15:
t0=0x04;
break;
}
j= b & 0x01;
j=(j<<3);
rot= (b>>1) | j;
des = (a<<3) & 0x0F;
t1= (a ^ rot) ^ (des);
switch ( t1 ) {
case 0:
t1=0x0E;
break;
case 1:
t1=0x0C;
80
break;
case 2:
t1=0x0B;
break;
case 3:
t1=0x08;
break;
case 4:
t1=0x01;
break;
case 5:
t1=0x02;
break;
case 6:
t1=0x03;
break;
case 7:
t1=0x05;
break;
case 8:
t1=0x0F;
break;
case 9:
t1=0x04;
break;
case 10:
t1=0x0A;
break;
case 11:
t1=0x06;
break;
case 12:
t1=0x07;
break;
case 13:
t1=0x00;
break;
case 14:
t1=0x09;
break;
case 15:
t1=0x0D;
break;
}
t2= t0 ^ t1;
switch ( t2 ) {
case 0:
t2=0x0B;
break;
case 1:
t2=0x0A;
break;
case 2:
t2=0x05;
break;
case 3:
t2=0x0E;
break;
81
case 4:
t2=0x06;
break;
case 5:
t2=0x0D;
break;
case 6:
t2=0x09;
break;
case 7:
t2=0x00;
break;
case 8:
t2=0x0C;
break;
case 9:
t2=0x08;
break;
case 10:
t2=0x0F;
break;
case 11:
t2=0x03;
break;
case 12:
t2=0x02;
break;
case 13:
t2=0x04;
break;
case 14:
t2=0x07;
break;
case 15:
t2=0x01;
break;
}
j= t1 & 0x01;
j=(j<<3);
rot= (t1>>1) | j;
des = (t0<<3) & 0x0F;
t3= (t0 ^ rot) ^ (des);
switch ( t3 ) {
case 0:
t3=0x0D;
break;
case 1:
t3=0x07;
break;
case 2:
t3=0x0F;
break;
case 3:
t3=0x04;
break;
case 4:
t3=0x01;
82
break;
case 5:
t3=0x02;
break;
case 6:
t3=0x06;
break;
case 7:
t3=0x0E;
break;
case 8:
t3=0x09;
break;
case 9:
t3=0x0B;
break;
case 10:
t3=0x03;
break;
case 11:
t3=0x00;
break;
case 12:
t3=0x08;
break;
case 13:
t3=0x05;
break;
case 14:
t3=0x0C;
break;
case 15:
t3=0x0A;
break;
}
out=(t3<<4) | t2;
}
/*
+*********************************************************************
********
*
* Function Name: permutacionq1
*
* Function: realiza el calculo de la caja q1
*
* Arguments: char in
* Return: char out
*
* Notes: Esta funcion calcula el valor de q1
*
-
**********************************************************************
******/
unsigned char permutacionq1(unsigned char in){
unsigned char t0,t1,t2,t3,j;
83
unsigned char a,b,rot,des,out;
a=((in & 0xF0)>>4);
b=(in & 0x0F);
t0= a ^ b;
switch ( t0 ) {
case 0:
t0=0x02;
break;
case 1:
t0=0x08;
break;
case 2:
t0=0x0B;
break;
case 3:
t0=0x0D;
break;
case 4:
t0=0x0F;
break;
case 5:
t0=0x07;
break;
case 6:
t0=0x06;
break;
case 7:
t0=0x0E;
break;
case 8:
t0=0x03;
break;
case 9:
t0=0x01;
break;
case 10:
t0=0x09;
break;
case 11:
t0=0x04;
break;
case 12:
t0=0x00;
break;
case 13:
t0=0x0A;
break;
case 14:
t0=0x0C;
break;
case 15:
t0=0x05;
break;
}
j= b & 0x01;
j=(j<<3);
rot= (b>>1) | j;
84
des = (a<<3) & 0x0F;
t1= (a ^ rot) ^ (des);
switch ( t1 ) {
case 0:
t1=0x01;
break;
case 1:
t1=0x0E;
break;
case 2:
t1=0x02;
break;
case 3:
t1=0x0B;
break;
case 4:
t1=0x04;
break;
case 5:
t1=0x0C;
break;
case 6:
t1=0x03;
break;
case 7:
t1=0x07;
break;
case 8:
t1=0x06;
break;
case 9:
t1=0x0D;
break;
case 10:
t1=0x0A;
break;
case 11:
t1=0x05;
break;
case 12:
t1=0x0F;
break;
case 13:
t1=0x09;
break;
case 14:
t1=0x00;
break;
case 15:
t1=0x08;
break;
}
t2= t0 ^ t1;
switch ( t2 ) {
case 0:
85
t2=0x04;
break;
case 1:
t2=0x0C;
break;
case 2:
t2=0x07;
break;
case 3:
t2=0x05;
break;
case 4:
t2=0x01;
break;
case 5:
t2=0x06;
break;
case 6:
t2=0x09;
break;
case 7:
t2=0x0A;
break;
case 8:
t2=0x00;
break;
case 9:
t2=0x0E;
break;
case 10:
t2=0x0D;
break;
case 11:
t2=0x08;
break;
case 12:
t2=0x02;
break;
case 13:
t2=0x0B;
break;
case 14:
t2=0x03;
break;
case 15:
t2=0x0F;
break;
}
j= t1 & 0x01;
j=(j<<3);
rot= (t1>>1) | j;
des = (t0<<3) & 0x0F;
t3= (t0 ^ rot) ^ (des);
switch ( t3 ) {
case 0:
t3=0x0B;
break;
86
case 1:
t3=0x09;
break;
case 2:
t3=0x05;
break;
case 3:
t3=0x01;
break;
case 4:
t3=0x0C;
break;
case 5:
t3=0x03;
break;
case 6:
t3=0x0D;
break;
case 7:
t3=0x0E;
break;
case 8:
t3=0x06;
break;
case 9:
t3=0x04;
break;
case 10:
t3=0x07;
break;
case 11:
t3=0x0F;
break;
case 12:
t3=0x02;
break;
case 13:
t3=0x00;
break;
case 14:
t3=0x08;
break;
case 15:
t3=0x0A;
break;
}
out=(t3<<4) | t2;
return out;
}
/*
+*********************************************************************
********
*
* Function Name: mds
*
87
* Function: Calcula el valor con la matriz para subclaves
*
* Arguments: char a,b,c.
* Return: char c
*
* Notes: Esta funcion calcula la multiplciacion en GF(2^8) en las
subclaves si
*
-
**********************************************************************
******/
unsigned char mds (unsigned char a, unsigned char b){
unsigned char out, res0,res1,res2,res3,res4,res5,res6,res7;
unsigned char vecbina[8];
unsigned char vecbinb[8];
unsigned char res[8];
vecbina[0]= a & 0x01;
vecbina[1]= (a & 0x02)>>1;
vecbina[2]= (a & 0x04)>>2;
vecbina[3]= (a & 0x08)>>3;
vecbina[4]= (a & 0x10)>>4;
vecbina[5]= (a & 0x20)>>5;
vecbina[6]= (a & 0x40)>>6;
vecbina[7]= (a & 0x80)>>7;
vecbinb[0]= b & 0x01;
vecbinb[1]= (b & 0x02)>>1;
vecbinb[2]= (b & 0x04)>>2;
vecbinb[3]= (b & 0x08)>>3;
vecbinb[4]= (b & 0x10)>>4;
vecbinb[5]= (b & 0x20)>>5;
vecbinb[6]= (b & 0x40)>>6;
vecbinb[7]= (b & 0x80)>>7;
res[0]= (vecbina[0]&vecbinb[0]) ^ (vecbina[7]&vecbinb[1]) ^
(vecbina[6]&vecbinb[2]) ^ ((vecbina[7]^vecbina[5])&vecbinb[3]) ^
((vecbina[7]^vecbina[6]^vecbina[4])&vecbinb[4]) ^
((vecbina[7]^vecbina[6]^vecbina[5]^vecbina[3])&vecbinb[5]) ^
((vecbina[7]^vecbina[6]^vecbina[5]^vecbina[4]^vecbina[2])&vecbinb[6])
^
((vecbina[6]^vecbina[5]^vecbina[4]^vecbina[3]^vecbina[1])&vecbinb[7]);
res[1]= (vecbina[1]&vecbinb[0]) ^ (vecbina[0]&vecbinb[1]) ^
(vecbina[7]&vecbinb[2]) ^ (vecbina[6]&vecbinb[3]) ^
((vecbina[7]^vecbina[5])&vecbinb[4]) ^
((vecbina[7]^vecbina[6]^vecbina[4])&vecbinb[5]) ^
((vecbina[7]^vecbina[6]^vecbina[5]^vecbina[3])&vecbinb[6]) ^
((vecbina[7]^vecbina[6]^vecbina[5]^vecbina[4]^vecbina[2])&vecbinb[7]);
res[2]= (vecbina[2]&vecbinb[0]) ^ (vecbina[1]&vecbinb[1]) ^
(vecbina[0]&vecbinb[2]) ^ (vecbina[7]&vecbinb[3]) ^
(vecbina[6]&vecbinb[4]) ^ ((vecbina[7]^vecbina[5])&vecbinb[5]) ^
((vecbina[7]^vecbina[6]^vecbina[4])&vecbinb[6]) ^
((vecbina[7]^vecbina[6]^vecbina[5]^vecbina[3])&vecbinb[7]);
88
res[3]= (vecbina[3]&vecbinb[0]) ^ ((vecbina[7]^vecbina[2])&vecbinb[1])
^ ((vecbina[6]^vecbina[1])&vecbinb[2]) ^
((vecbina[7]^vecbina[5]^vecbina[0])&vecbinb[3]) ^
((vecbina[6]^vecbina[4])&vecbinb[4]) ^
((vecbina[7]^vecbina[5]^vecbina[3])&vecbinb[5]) ^
((vecbina[6]^vecbina[4]^vecbina[2])&vecbinb[6]) ^
((vecbina[7]^vecbina[5]^vecbina[3]^vecbina[1])&vecbinb[7]);
res[4]= (vecbina[4]&vecbinb[0]) ^ (vecbina[3]&vecbinb[1]) ^
((vecbina[7]^vecbina[2])&vecbinb[2]) ^
((vecbina[6]^vecbina[1])&vecbinb[3]) ^
((vecbina[7]^vecbina[5]^vecbina[0])&vecbinb[4]) ^
((vecbina[6]^vecbina[4])&vecbinb[5]) ^
((vecbina[7]^vecbina[5]^vecbina[3])&vecbinb[6]) ^
((vecbina[6]^vecbina[4]^vecbina[2])&vecbinb[7]);
res[5]= (vecbina[5]&vecbinb[0]) ^ ((vecbina[7]^vecbina[4])&vecbinb[1])
^ ((vecbina[6]^vecbina[3])&vecbinb[2]) ^
((vecbina[5]^vecbina[2])&vecbinb[3]) ^
((vecbina[7]^vecbina[4]^vecbina[1])&vecbinb[4]) ^
((vecbina[6]^vecbina[3]^vecbina[0])&vecbinb[5]) ^
((vecbina[7]^vecbina[5]^vecbina[2])&vecbinb[6]) ^
((vecbina[7]^vecbina[6]^vecbina[4]^vecbina[1])&vecbinb[7]);
res[6]= (vecbina[6]&vecbinb[0]) ^ ((vecbina[7]^vecbina[5])&vecbinb[1])
^ ((vecbina[7]^vecbina[6]^vecbina[4])&vecbinb[2]) ^
((vecbina[7]^vecbina[6]^vecbina[5]^vecbina[3])&vecbinb[3]) ^
((vecbina[7]^vecbina[6]^vecbina[5]^vecbina[4]^vecbina[2])&vecbinb[4])
^
((vecbina[6]^vecbina[5]^vecbina[4]^vecbina[3]^vecbina[1])&vecbinb[5])
^
((vecbina[7]^vecbina[5]^vecbina[4]^vecbina[3]^vecbina[2]^vecbina[0])&v
ecbinb[6]) ^
((vecbina[7]^vecbina[6]^vecbina[4]^vecbina[3]^vecbina[2]^vecbina[1])&v
ecbinb[7]);
res[7]= (vecbina[7]&vecbinb[0]) ^ (vecbina[6]&vecbinb[1]) ^
((vecbina[7]^vecbina[5])&vecbinb[2]) ^
((vecbina[7]^vecbina[6]^vecbina[4])&vecbinb[3]) ^
((vecbina[7]^vecbina[6]^vecbina[5]^vecbina[3])&vecbinb[4]) ^
((vecbina[7]^vecbina[6]^vecbina[5]^vecbina[4]^vecbina[2])&vecbinb[5])
^
((vecbina[6]^vecbina[5]^vecbina[4]^vecbina[3]^vecbina[1])&vecbinb[6])
^
((vecbina[7]^vecbina[5]^vecbina[4]^vecbina[3]^vecbina[2]^vecbina[0])&v
ecbinb[7]);
if(res[0]==0x00){
res0=0x00;
}else{
res0=0x01;
}
if(res[1]==0x00){
res1=0x00;
}else{
res1=0x02;
}
if(res[2]==0x00){
res2=0x00;
89
}else{
res2=0x04;
}
if(res[3]==0x00){
res3=0x00;
}else{
res3=0x08;
}
if(res[4]==0x00){
res4=0x00;
}else{
res4=0x10;
}
if(res[5]==0x00){
res5=0x00;
}else{
res5=0x20;
}
if(res[6]==0x00){
res6=0x00;
}else{
res6=0x40;
}
if(res[7]==0x00){
res7=0x00;
}else{
res7=0x80;
}
out= res0|res1|res2|res3|res4|res5|res6|res7;
return out;
}
/*
+*********************************************************************
********
*
* Function Name: funcion h
*
* Function: realiza el calculo de entrada a las cajas q0 y
q1, realiza las xor
con los valores de M, y realiza el
calculo de la matriz MDS
*
* Arguments: char i, int m1, int m2
* Return: char out
*
* Notes: calcula el valore de 32 bits a la salida de la matriz MDS
*
90
-
**********************************************************************
******/
unsigned int funcionh(unsigned char i, unsigned int m1, unsigned int
m2){
unsigned char
a0,b0,c0,d0,a1,b1,c1,d1,a2,b2,c2,d2,a3,b3,c3,d3,a4,b4,c4,d4; //son
utiles para las entradas a las permutaciones
unsigned int a, b, c; // son utiles
para concatenar los resultados y realizar la xor con las M1 y M2
unsigned char y0,y1,y2,y3; // son
utiles para la entrada a la matriz MDS
unsigned char mds0,mds1,mds2,mds3; //
son utiles para los resultados provenientes de la multiplicacion de la
matriz con la columna
unsigned char mdsa,mdsb,mdsc,mdsd; // son
utiles para guardar los resultados de la multiplicacion por fila
unsigned int out; //
es el resultado final de la funcion h
a0=permutacionq0(i);
b0=permutacionq1(i);
c0=permutacionq0(i);
d0=permutacionq1(i);
a=(d0<<24) | (c0<<16) | (b0<<8) | (a0);
a= a ^ m1;
a1=a;
b1=(a>>8);
c1=(a>>16);
d1=(a>>24);
a2=permutacionq0(a1);
b2=permutacionq0(b1);
c2=permutacionq1(c1);
d2=permutacionq1(d1);
b=(d2<<24) | (c2<<16) | (b2<<8) | (a2);
b= b ^ m2;
a3=b;
b3=(b>>8);
c3=(b>>16);
d3=(b>>24);
a4=permutacionq1(a3);
b4=permutacionq0(b3);
c4=permutacionq1(c3);
d4=permutacionq0(d3);
//entrada a la MDS
c=(d4<<24) | (c4<<16) | (b4<<8) | (a4);
y0=c;
y1=(c>>8);
y2=(c>>16);
91
y3=(c>>24);
//primera fila
mds0=mds(0x01,y0);
mds1=mds(0xEF,y1);
mds2=mds(0x5B,y2);
mds3=mds(0x5B,y3);
mdsa=mds0 ^ mds1 ^ mds2 ^ mds3;
//segunda fila
mds0=mds(0x5B,y0);
mds1=mds(0xEF,y1);
mds2=mds(0xEF,y2);
mds3=mds(0x01,y3);
mdsb=mds0 ^ mds1 ^ mds2 ^ mds3;
//tercera fila
mds0=mds(0xEF,y0);
mds1=mds(0x5B,y1);
mds2=mds(0x01,y2);
mds3=mds(0xEF,y3);
mdsc=mds0 ^ mds1 ^ mds2 ^ mds3;
//cuarta fila
mds0=mds(0xEF,y0);
mds1=mds(0x01,y1);
mds2=mds(0xEF,y2);
mds3=mds(0x5B,y3);
mdsd=mds0 ^ mds1 ^ mds2 ^ mds3;
out=(mdsd<<24) | (mdsc<<16) | (mdsb<<8) | (mdsa);
return out;
}
/*
+*********************************************************************
********
*
* Function Name: funcion f
*
* Function: realiza el calculo de entrada a las cajas q0 y
q1, realiza las xor
con los valores de M, y realiza el
calculo de la matriz MDS
*
* Arguments: char i, int m1, int m2
* Return: char out
*
* Notes: calcula el valore de 32 bits a la salida de la matriz MDS
*
92
-
**********************************************************************
******/
unsigned int funcionf(unsigned int i, unsigned int s0, unsigned int
s1){
unsigned char
a0,b0,c0,d0,a1,b1,c1,d1,a2,b2,c2,d2,a3,b3,c3,d3,a4,b4,c4,d4; //son
utiles para las entradas a las permutaciones
unsigned int a, b, c; // son utiles
para concatenar los resultados y realizar la xor con las M1 y M2
unsigned char y0,y1,y2,y3; // son
utiles para la entrada a la matriz MDS
unsigned char mds0,mds1,mds2,mds3; //
son utiles para los resultados provenientes de la multiplicacion de la
matriz con la columna
unsigned char mdsa,mdsb,mdsc,mdsd; // son
utiles para guardar los resultados de la multiplicacion por fila
unsigned int out; //
es el resultado final de la funcion h
unsigned char q0,q1,q2,q3;
q0=i;
q1=i>>8;
q2=i>>16;
q3=i>>24;
a0=permutacionq0(q0);
b0=permutacionq1(q1);
c0=permutacionq0(q2);
d0=permutacionq1(q3);
a=(d0<<24) | (c0<<16) | (b0<<8) | (a0);
a= a ^ s0;
a1=a;
b1=(a>>8);
c1=(a>>16);
d1=(a>>24);
a2=permutacionq0(a1);
b2=permutacionq0(b1);
c2=permutacionq1(c1);
d2=permutacionq1(d1);
b=(d2<<24) | (c2<<16) | (b2<<8) | (a2);
b= b ^ s1;
a3=b;
b3=(b>>8);
c3=(b>>16);
d3=(b>>24);
a4=permutacionq1(a3);
b4=permutacionq0(b3);
c4=permutacionq1(c3);
d4=permutacionq0(d3);
93
//entrada a la MDS
c=(d4<<24) | (c4<<16) | (b4<<8) | (a4);
y0=c;
y1=(c>>8);
y2=(c>>16);
y3=(c>>24);
//primera fila
mds0=mds(0x01,y0);
mds1=mds(0xEF,y1);
mds2=mds(0x5B,y2);
mds3=mds(0x5B,y3);
mdsa=mds0 ^ mds1 ^ mds2 ^ mds3;
//segunda fila
mds0=mds(0x5B,y0);
mds1=mds(0xEF,y1);
mds2=mds(0xEF,y2);
mds3=mds(0x01,y3);
mdsb=mds0 ^ mds1 ^ mds2 ^ mds3;
//tercera fila
mds0=mds(0xEF,y0);
mds1=mds(0x5B,y1);
mds2=mds(0x01,y2);
mds3=mds(0xEF,y3);
mdsc=mds0 ^ mds1 ^ mds2 ^ mds3;
//cuarta fila
mds0=mds(0xEF,y0);
mds1=mds(0x01,y1);
mds2=mds(0xEF,y2);
mds3=mds(0x5B,y3);
mdsd=mds0 ^ mds1 ^ mds2 ^ mds3;
out=(mdsd<<24) | (mdsc<<16) | (mdsb<<8) | (mdsa);
return out;
}
/*
+*********************************************************************
********
*
* Function Name: generarclaves
*
* Function: Realiza el calculo de las claves kp y ki
*
* Arguments: int i, int m0, int m1, int m2, int m3
94
* Return: int kp, int ki
*
* Notes: Esta funcion calcula el valor de las claves kp y ki
*
-
**********************************************************************
******/
unsigned int generarclaves(unsigned char i,unsigned char clave[]){
unsigned int ki;
unsigned char par= i*2;
unsigned char impar = (i*2)+1;
int a0,b0,b0r;
unsigned int j;
unsigned int m0,m1,m2,m3;
m0=(clave[3]<<24) |(clave[2]<<16) | (clave[1]<<8) |(clave[0]);
m1=(clave[7]<<24) |(clave[6]<<16) | (clave[5]<<8) |(clave[4]);
m2=(clave[11]<<24) |(clave[10]<<16) | (clave[9]<<8) |(clave[8]);
m3=(clave[15]<<24) |(clave[14]<<16) | (clave[13]<<8) |(clave[12]);
a0=funcionh(par, m2, m0);
b0=funcionh(impar,m3,m1);
j= b0 & 0xFF000000;
j= (j>>24);
b0r= (b0<<8) | j;
kp=phta(a0,b0r);
ki=phtb(a0,b0r);
j= ki & 0xFF800000;
j=(j>>23);
kir=(ki<<9) | j;
}
/*
+*********************************************************************
********
*
* Function Name: mult
*
* Function: Calcula el valor con la matriz para subclaves
*
* Arguments: char a,b,c.
* Return: char c
*
* Notes: Esta funcion calcula la multiplciacion en GF(2^8) en las
subclaves si
*
95
-
**********************************************************************
******/
unsigned char mult(unsigned char a, unsigned char b){
unsigned char out, res0,res1,res2,res3,res4,res5,res6,res7;
unsigned char vecbina[8];
unsigned char vecbinb[8];
unsigned char res[8];
vecbina[0]= a & 0x01;
vecbina[1]= (a & 0x02)>>1;
vecbina[2]= (a & 0x04)>>2;
vecbina[3]= (a & 0x08)>>3;
vecbina[4]= (a & 0x10)>>4;
vecbina[5]= (a & 0x20)>>5;
vecbina[6]= (a & 0x40)>>6;
vecbina[7]= (a & 0x80)>>7;
vecbinb[0]= b & 0x01;
vecbinb[1]= (b & 0x02)>>1;
vecbinb[2]= (b & 0x04)>>2;
vecbinb[3]= (b & 0x08)>>3;
vecbinb[4]= (b & 0x10)>>4;
vecbinb[5]= (b & 0x20)>>5;
vecbinb[6]= (b & 0x40)>>6;
vecbinb[7]= (b & 0x80)>>7;
res[0]= (vecbina[0]&vecbinb[0]) ^ (vecbina[7]&vecbinb[1]) ^
(vecbina[6]&vecbinb[2]) ^ ((vecbina[7]^vecbina[5])&vecbinb[3]) ^
((vecbina[6]^vecbina[4])&vecbinb[4]) ^
((vecbina[7]^vecbina[5]^vecbina[3])&vecbinb[5]) ^
((vecbina[7]^vecbina[6]^vecbina[4]^vecbina[2])&vecbinb[6]) ^
((vecbina[6]^vecbina[5]^vecbina[3]^vecbina[1])&vecbinb[7]);
res[1]= (vecbina[1]&vecbinb[0]) ^ (vecbina[0]&vecbinb[1]) ^
(vecbina[7]&vecbinb[2]) ^ (vecbina[6]&vecbinb[3]) ^
((vecbina[7]^vecbina[5])&vecbinb[4]) ^
((vecbina[6]^vecbina[4])&vecbinb[5]) ^
((vecbina[7]^vecbina[5]^vecbina[3])&vecbinb[6]) ^
((vecbina[7]^vecbina[6]^vecbina[4]^vecbina[2])&vecbinb[7]);
res[2]= (vecbina[2]&vecbinb[0]) ^ ((vecbina[7]^vecbina[1])&vecbinb[1])
^ ((vecbina[6]^vecbina[0])&vecbinb[2]) ^ (vecbina[5]&vecbinb[3]) ^
(vecbina[4]&vecbinb[4]) ^ (vecbina[3]&vecbinb[5]) ^
((vecbina[7]^vecbina[2])&vecbinb[6]) ^
((vecbina[7]^vecbina[6]^vecbina[1])&vecbinb[7]);
res[3]= (vecbina[3]&vecbinb[0]) ^ ((vecbina[7]^vecbina[2])&vecbinb[1])
^ ((vecbina[7]^vecbina[6]^vecbina[1])&vecbinb[2]) ^
((vecbina[7]^vecbina[6]^vecbina[5]^vecbina[0])&vecbinb[3]) ^
((vecbina[6]^vecbina[5]^vecbina[4])&vecbinb[4]) ^
((vecbina[7]^vecbina[5]^vecbina[4]^vecbina[3])&vecbinb[5]) ^
((vecbina[7]^vecbina[6]^vecbina[4]^vecbina[3]^vecbina[2])&vecbinb[6])
^
((vecbina[7]^vecbina[6]^vecbina[5]^vecbina[3]^vecbina[2]^vecbina[1])&v
ecbinb[7]);
res[4]= (vecbina[4]&vecbinb[0]) ^ (vecbina[3]&vecbinb[1]) ^
((vecbina[7]^vecbina[2])&vecbinb[2]) ^
((vecbina[7]^vecbina[6]^vecbina[1])&vecbinb[3]) ^
96
((vecbina[7]^vecbina[6]^vecbina[5]^vecbina[0])&vecbinb[4]) ^
((vecbina[6]^vecbina[5]^vecbina[4])&vecbinb[5]) ^
((vecbina[7]^vecbina[5]^vecbina[4]^vecbina[3])&vecbinb[6]) ^
((vecbina[7]^vecbina[6]^vecbina[4]^vecbina[3]^vecbina[2])&vecbinb[7]);
res[5]= (vecbina[5]&vecbinb[0]) ^ (vecbina[4]&vecbinb[1]) ^
(vecbina[3]&vecbinb[2]) ^ ((vecbina[7]^vecbina[2])&vecbinb[3]) ^
((vecbina[7]^vecbina[6]^vecbina[1])&vecbinb[4]) ^
((vecbina[7]^vecbina[6]^vecbina[5]^vecbina[0])&vecbinb[5]) ^
((vecbina[6]^vecbina[5]^vecbina[4])&vecbinb[6]) ^
((vecbina[7]^vecbina[5]^vecbina[4]^vecbina[3])&vecbinb[7]);
res[6]= (vecbina[6]&vecbinb[0]) ^ ((vecbina[7]^vecbina[5])&vecbinb[1])
^ ((vecbina[6]^vecbina[4])&vecbinb[2]) ^
((vecbina[7]^vecbina[5]^vecbina[3])&vecbinb[3]) ^
((vecbina[7]^vecbina[6]^vecbina[4]^vecbina[2])&vecbinb[4]) ^
((vecbina[6]^vecbina[5]^vecbina[3]^vecbina[1])&vecbinb[5]) ^
((vecbina[5]^vecbina[4]^vecbina[2]^vecbina[0])&vecbinb[6]) ^
((vecbina[4]^vecbina[3]^vecbina[1])&vecbinb[7]);
res[7]= (vecbina[7]&vecbinb[0]) ^ (vecbina[6]&vecbinb[1]) ^
((vecbina[7]^vecbina[5])&vecbinb[2]) ^
((vecbina[6]^vecbina[4])&vecbinb[3]) ^
((vecbina[7]^vecbina[5]^vecbina[3])&vecbinb[4]) ^
((vecbina[7]^vecbina[6]^vecbina[4]^vecbina[2])&vecbinb[5]) ^
((vecbina[6]^vecbina[5]^vecbina[3]^vecbina[1])&vecbinb[6]) ^
((vecbina[5]^vecbina[4]^vecbina[2]^vecbina[0])&vecbinb[7]);
if(res[0]==0x00){
res0=0x00;
}else{
res0=0x01;
}
if(res[1]==0x00){
res1=0x00;
}else{
res1=0x02;
}
if(res[2]==0x00){
res2=0x00;
}else{
res2=0x04;
}
if(res[3]==0x00){
res3=0x00;
}else{
res3=0x08;
}
if(res[4]==0x00){
res4=0x00;
}else{
res4=0x10;
}
if(res[5]==0x00){unsigned int kp;
unsigned int kir;
res5=0x00;
97
}else{
res5=0x20;
}
if(res[6]==0x00){
res6=0x00;
}else{
res6=0x40;
}
if(res[7]==0x00){
res7=0x00;
}else{
res7=0x80;
}
out= res0|res1|res2|res3|res4|res5|res6|res7;
return out;
}
/*
+*********************************************************************
********
*
* Function Name: Subclaves s0 y s1
*
* Function: Calcula las sublcaves s0 y s1
*
* Arguments: int cl0,cl1,cl2,cl3, es la clave dividida en 4
variables de 32 bits
* Return: s0,s1 los cuales son dos variables de 32 bits
*
* Notes: Esta funcion calcula las subclaves s0 y s1 los cuales son
constantes
a lo largo del proceso.
*
-
**********************************************************************
******/
unsigned int subclavesi(unsigned char clave[]){
unsigned char
m0,m1,m2,m3,m4,m5,m6,m7,m8,m9,m10,m11,m12,m13,m14,m15;
unsigned char
a00,b00,c00,d00,e00,f00,g00,h00,s00,s01,s02,s03,s10,s11,s12,s13;
m0= (clave[15]);
m1= (clave[14]);
m2= (clave[13]);
m3= (clave[12]);
m4= (clave[11]);
m5= (clave[10]);
m6= (clave[9]);
m7= (clave[8]);
/* para s1 */
98
m8= (clave[7]);
m9= (clave[6]);
m10= (clave[5]);
m11= (clave[4]);
m12= (clave[3]);
m13= (clave[2]);
m14= (clave[1]);
m15= (clave[0]);
/* para s0,0 */
a00=mult(0x01, m0);
b00=mult(0xa4, m1);
c00=mult(0x55, m2);
d00=mult(0x87, m3);
e00=mult(0x5a, m4);
f00=mult(0x58, m5);
g00=mult(0xdb, m6);
h00=mult(0x9e, m7);
s00= a00 ^ b00 ^ c00 ^ d00 ^ e00 ^ f00 ^ g00 ^ h00;
/* para s0,1 */
a00=mult(0xa4, m0);
b00=mult(0x56, m1);
c00=mult(0x82, m2);
d00=mult(0xf3, m3);
e00=mult(0x1e, m4);
f00=mult(0xc6, m5);
g00=mult(0x68, m6);
h00=mult(0xe5, m7);
s01= a00 ^ b00 ^ c00 ^ d00 ^ e00 ^ f00 ^ g00 ^ h00;
/* para s0,2 */
a00=mult(0x02, m0);
b00=mult(0xa1, m1);
c00=mult(0xfc, m2);
d00=mult(0xc1, m3);
e00=mult(0x47, m4);
f00=mult(0xae, m5);
g00=mult(0x3d, m6);
h00=mult(0x19, m7);
s02= a00 ^ b00 ^ c00 ^ d00 ^ e00 ^ f00 ^ g00 ^ h00;
/* para s0,3 */
a00=mult(0xa4, m0);
b00=mult(0x55, m1);
c00=mult(0x87, m2);
d00=mult(0x5a, m3);
e00=mult(0x58, m4);
f00=mult(0xdb, m5);
g00=mult(0x9e, m6);
h00=mult(0x03, m7);
s03= a00 ^ b00 ^ c00 ^ d00 ^ e00 ^ f00 ^ g00 ^ h00;
99
/*clave s0*/
cs0= (s03<<24) | (s02<<16) | (s01<<8) | s00;
/* para s1,0 */
a00=mult(0x01, m8);
b00=mult(0xa4, m9);
c00=mult(0x55, m10);
d00=mult(0x87, m11);
e00=mult(0x5a, m12);
f00=mult(0x58, m13);
g00=mult(0xdb, m14);
h00=mult(0x9e, m15);
s10= a00 ^ b00 ^ c00 ^ d00 ^ e00 ^ f00 ^ g00 ^ h00;
/* para s1,1 */
a00=mult(0xa4, m8);
b00=mult(0x56, m9);
c00=mult(0x82, m10);
d00=mult(0xf3, m11);
e00=mult(0x1e, m12);
f00=mult(0xc6, m13);
g00=mult(0x68, m14);
h00=mult(0xe5, m15);
s11= a00 ^ b00 ^ c00 ^ d00 ^ e00 ^ f00 ^ g00 ^ h00;
/* para s1,2 */
a00=mult(0x02, m8);
b00=mult(0xa1, m9);
c00=mult(0xfc, m10);
d00=mult(0xc1, m11);
e00=mult(0x47, m12);
f00=mult(0xae, m13);
g00=mult(0x3d, m14);
h00=mult(0x19, m15);
s12= a00 ^ b00 ^ c00 ^ d00 ^ e00 ^ f00 ^ g00 ^ h00;
/* para s1,3 */
a00=mult(0xa4, m8);
b00=mult(0x55, m9);
c00=mult(0x87, m10);
d00=mult(0x5a, m11);
e00=mult(0x58, m12);
f00=mult(0xdb, m13);
g00=mult(0x9e, m14);
h00=mult(0x03, m15);
s13= a00 ^ b00 ^ c00 ^ d00 ^ e00 ^ f00 ^ g00 ^ h00;
/*clave s1*/
cs1= (s13<<24) | (s12<<16) | (s11<<8) | s10;
}
/*
100
+*********************************************************************
********
*
* Function Name: ronda
*
* Function: Realiza una ronda
*
* Arguments: int a,b,c,d
* Return: int a,b,c,d
*
* Notes: Esta funcion es una ronda de las 16 que se realizan en el
algoritmo
*
-
**********************************************************************
******/
unsigned int ronda(unsigned int r,unsigned int aa, unsigned int bb,
unsigned int cc, unsigned int dd){
unsigned int a1,b1,z,y,brot;
unsigned int j;
a1=funcionf(aa, cs0, cs1);
//roto las 8 posiciones
j= bb & 0xFF000000;
j= j>>24;
brot= (bb<<8) | j;
b1=funcionf(brot, cs0, cs1);
//transformada phta
z=phta(a1,b1);
//sumo la clave correspondiente a la ronda r
z= z + k[((2*r)+8)];
//hago la xor con c, la cual es el resultado del blanqueo
inicial
z= z ^ cc;
//roto una posicion a la derecha
j= z & 0x00000001;
j= j<<31;
z= (z>>1) | j;
//transformada phtb
y=phtb(a1,b1);
//sumo la clave correspondiente a la ronda r
y= y + k[(2*r)+9];
//roto d una posicion a la izquierda
j= dd & 0x80000000;
j= j>>31;
dd= (dd<<1) | j;
//hago la xor con d, la cual es el resultado del blanqueo
inicial
101
y= y ^ dd;
//actualizo las variables a,b,c,d
d=bb;
c=aa;
b=y;
a=z;
}
/*
+*********************************************************************
********
*
* Function Name: ronda desencriptacion
*
* Function: Realiza una ronda
*
* Arguments: int a,b,c,d
* Return: int a,b,c,d
*
* Notes: Esta funcion es una ronda de las 16 que se realizan en el
algoritmo
*
-
**********************************************************************
******/
unsigned int rondades(unsigned int r,unsigned int aa, unsigned int bb,
unsigned int cc, unsigned int dd){
unsigned int a1,b1,z,y,brot;
unsigned int j;
a1=funcionf(aa, cs0, cs1);
//roto las 8 posiciones
j= bb & 0xFF000000;
j= j>>24;
brot= (bb<<8) | j;
b1=funcionf(brot, cs0, cs1);
//transformada phta
z=phta(a1,b1);
//sumo la clave correspondiente a la ronda r
z= z + k[(38-(2*r))];
//roto c una posicion a la izquierda
j= cc & 0x80000000;
j= j>>31;
cc= (cc<<1) | j;
//hago la xor con c, la cual es el resultado del blanqueo
inicial
102
z= z ^ cc;
//transformada phtb
y=phtb(a1,b1);
//sumo la clave correspondiente a la ronda r
y= y + k[39-(2*r)];
//hago la xor con d, la cual es el resultado del blanqueo
inicial
y= y ^ dd;
//roto d una posicion a la derecha
j= y & 0x00000001;
j= j<<31;
y= (y>>1) | j;
//actualizo las variables a,b,c,d
d=bb;
c=aa;
b=y;
a=z;
}
/*
+*********************************************************************
********
*
* Function Name: ENCRIPTAR
*
* Function: encripta un texto plano de 128 bits con una
clave de la misma longitud
*
* Arguments: int pt0,pt1,pt2,pt3,cl0,cl1,cl2,cl3
* Return: int a,b,c,d
*
* Notes: Esta funcion realiza la encriptacion de un texto mediante el
algoritmo twofish
*
-
**********************************************************************
******/
unsigned int encriptar(unsigned char texto[], unsigned char cifrado[],
unsigned char clave[]){
unsigned int pt00 = texto[0] | texto[1]<<8 | texto[2]<<16 |
texto[3]<<24;
unsigned int pt01 = texto[4] | texto[5]<<8 | texto[6]<<16 |
texto[7]<<24;
unsigned int pt02 = texto[8] | texto[9]<<8 | texto[10]<<16 |
texto[11]<<24;
unsigned int pt03 = texto[12] | texto[13]<<8 | texto[14]<<16 |
texto[15]<<24;
103
unsigned int i,rond,save1,save2,f1,f2,f3,f4;
//generacion de las claves S0 y S1 las cuales son constantes y son
utiles para las rondas
subclavesi(clave);
//generacion de las 40 claves k
for(i=0;i<20;i++){
generarclaves(i,clave);
k[2*i]=kp;
k[(2*i)+1]=kir;
}
//blanqueo inicial
a=k[0] ^ pt03;
b=k[1] ^ pt02;
c=k[2] ^ pt01;
d=k[3] ^ pt00;
//16 rondas
for(rond=0;rond<16;rond++){
ronda(rond,a,b,c,d);
}
//Deshago la ultima rotacion
save1=a;
save2=b;
a=c;
b=d;
c=save1;
d=save2;
//blanqueo de salida
a= a ^ k[4];
b= b ^ k[5];
c= c ^ k[6];
d= d ^ k[7];
//SWAP
f1= a & 0xFF000000;
f1= f1>>24;
f2= a & 0x00FF0000;
f2= f2>>8;
f3= a & 0x0000FF00;
f3= f3<<8;
f4= a & 0x000000FF;
f4= f4<<24;
a= f1 | f2 | f3 | f4;
104
f1= b & 0xFF000000;
f1= f1>>24;
f2= b & 0x00FF0000;
f2= f2>>8;
f3= b & 0x0000FF00;
f3= f3<<8;
f4= b & 0x000000FF;
f4= f4<<24;
b= f1 | f2 | f3 | f4;
f1= c & 0xFF000000;
f1= f1>>24;
f2= c & 0x00FF0000;
f2= f2>>8;
f3= c & 0x0000FF00;
f3= f3<<8;
f4= c & 0x000000FF;
f4= f4<<24;
c= f1 | f2 | f3 | f4;
f1= d & 0xFF000000;
f1= f1>>24;
f2= d & 0x00FF0000;
f2= f2>>8;
f3= d & 0x0000FF00;
f3= f3<<8;
f4= d & 0x000000FF;
f4= f4<<24;
d= f1 | f2 | f3 | f4;
cifrado[15] = (a&0xff000000)>>24;
cifrado[14] = (a&0x00ff0000)>>16;
cifrado[13] = (a&0x0000ff00)>>8;
cifrado[12] = (a&0x000000ff);
cifrado[11] = (b&0xff000000)>>24;
cifrado[10] = (b&0x00ff0000)>>16;
cifrado[9] = (b&0x0000ff00)>>8;
cifrado[8] = (b&0x000000ff);
cifrado[7] = (c&0xff000000)>>24;
cifrado[6] = (c&0x00ff0000)>>16;
cifrado[5] = (c&0x0000ff00)>>8;
cifrado[4] = (c&0x000000ff);
cifrado[3] = (d&0xff000000)>>24;
cifrado[2] = (d&0x00ff0000)>>16;
cifrado[1] = (d&0x0000ff00)>>8;
cifrado[0] = (d&0x000000ff);
}
/*
+*********************************************************************
********
*
* Function Name: DESENCRIPTAR
*
105
* Function: encripta un texto plano de 128 bits con una
clave de la misma longitud
*
* Arguments: int pt0,pt1,pt2,pt3,cl0,cl1,cl2,cl3
* Return: int a,b,c,d
*
* Notes: Esta funcion realiza la encriptacion de un texto mediante el
algoritmo twofish
*
-
**********************************************************************
******/
unsigned int desencriptar(unsigned char texto[], unsigned char
cifrado[], unsigned char clave[]){
unsigned int i,rond,save1,save2,f1,f2,f3,f4;
unsigned int cl00, cl01, cl02, cl03;
d=(cifrado[3]<<24) |(cifrado[2]<<16) | (cifrado[1]<<8)
|(cifrado[0]);
c=(cifrado[7]<<24) |(cifrado[6]<<16) | (cifrado[5]<<8)
|(cifrado[4]);
b=(cifrado[11]<<24) |(cifrado[10]<<16) | (cifrado[9]<<8)
|(cifrado[8]);
a=(cifrado[15]<<24) |(cifrado[14]<<16) | (cifrado[13]<<8)
|(cifrado[12]);
cl00=(clave[3]<<24) |(clave[2]<<16) | (clave[1]<<8) |(clave[0]);
cl01=(clave[7]<<24) |(clave[6]<<16) | (clave[5]<<8) |(clave[4]);
cl02=(clave[11]<<24) |(clave[10]<<16) | (clave[9]<<8) |(clave[8]);
cl03=(clave[15]<<24) |(clave[14]<<16) | (clave[13]<<8)
|(clave[12]);
// printf("CIFRADO: %x ",a);
// printf("%x ",b);
// printf("%x ",c);
// printf("%x \n",d);
//generacion de las claves S0 y S1 las cuales son constantes y
son utiles para las rondas
subclavesi(clave);
//generacion de las 40 claves k
for(i=0;i<20;i++){
generarclaves(i,clave);
k[2*i]=kp;
k[(2*i)+1]=kir;
}
//SWAP
f1= a & 0xFF000000;
f1= f1>>24;
106
f2= a & 0x00FF0000;
f2= f2>>8;
f3= a & 0x0000FF00;
f3= f3<<8;
f4= a & 0x000000FF;
f4= f4<<24;
a= f1 | f2 | f3 | f4;
f1= b & 0xFF000000;
f1= f1>>24;
f2= b & 0x00FF0000;
f2= f2>>8;
f3= b & 0x0000FF00;
f3= f3<<8;
f4= b & 0x000000FF;
f4= f4<<24;
b= f1 | f2 | f3 | f4;
f1= c & 0xFF000000;
f1= f1>>24;
f2= c & 0x00FF0000;
f2= f2>>8;
f3= c & 0x0000FF00;
f3= f3<<8;
f4= c & 0x000000FF;
f4= f4<<24;
c= f1 | f2 | f3 | f4;
f1= d & 0xFF000000;
f1= f1>>24;
f2= d & 0x00FF0000;
f2= f2>>8;
f3= d & 0x0000FF00;
f3= f3<<8;
f4= d & 0x000000FF;
f4= f4<<24;
d= f1 | f2 | f3 | f4;
//blanqueo de entrada
a= a ^ k[4];
b= b ^ k[5];
c= c ^ k[6];
d= d ^ k[7];
//16 rondas
for(rond=0;rond<16;rond++){
rondades(rond,a,b,c,d);
}
107
//Deshago la ultima rotacion
save1=a;
save2=b;
a=c;
b=d;
c=save1;
d=save2;
//blanqueo inicial
pt3=k[0] ^ a;
pt2=k[1] ^ b;
pt1=k[2] ^ c;
pt0=k[3] ^ d;
texto[15]= (pt3>>24);
texto[14]= (pt3>>16);
texto[13]= (pt3>>8);
texto[12]= (pt3);
texto[11]= (pt2>>24);
texto[10]= (pt2>>16);
texto[9]= (pt2>>8);
texto[8]= (pt2);
texto[7]= (pt1>>24);
texto[6]= (pt1>>16);
texto[5]= (pt1>>8);
texto[4]= (pt1);
texto[3]= (pt0>>24);
texto[2]= (pt0>>16);
texto[1]= (pt0>>8);
texto[0]= (pt0);
}