howto.dox
7.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/** @file
\author Imanol Barba Sabariego
\date 13/06/2013
\page howto HOWTO
\brief Descripción de funcionamiento y uso de la librería.
\tableofcontents
A continuación se desglosan las instrucciones para el desarrollo con esta libería y su posterior uso.
<br><br>
\section proto Descripción del protocolo
En las comunicaciones con Sockets hay un problema, es fácil saber la longitud del mensaje que vas a enviar, pero cuesta saber la longitud del mensaje que deseas recibir, ya que la transmisión se puede detener por llegar al fin del mensaje o bien por que hay problemas en la red.
Los sockets de UNIX nos dan una solución, que es usar llamadas no bloqueantes para recibir el mensaje, es decir: Si leo de un socket, y no he llenado el buffer donde guardo los datos que recibo de allí, la aplicación no se bloquea esperando recibir la suficiente cantidad de datos. A su vez, se usan llamadas a la función <a href="http://linux.die.net/man/2/select">select()</a> para comprovar si hay datos disponibles a para leer o la conexión está terminada.
Esto requiere uso de la forks e ir haciendo encuesta (polling) al socket, cosa que consume más recursos del sistema.
Debido a la complejidad añadida que supone hacerlo por esta vía, ya que la librería usa threads que son más ligeros para el sistema y la memoria RAM; se ha optado por implementar un sencillísimo protocolo de comunicación que no supone gasto de computación y repercute de forma nímia en el rendimiento de la transferencia.
A este protocolo hay que sumarle la encriptación implementada en esta libería, a continuación se detallan los posibles escenarios.
<br>
\subsection crypt Modo encriptado
Este caso se da cuando se habilita la encriptación (véase: \ref defines), en este modo la comunicación se realiza en dos fases: \ref key y \ref send_crypt. La encriptación implementada en esta librería es encriptación híbrida; para entender estos conceptos aclararemos algunos conceptos de criptografía:
- Criptografía simétrica: Método para encriptar mensajes con clave, donde la misma clave que se usa para encriptarlo, sirve para desencriptarlo.
- Criptografía asimétrica: Método para encriptar mensajes con clave, donde se generan dos claves, una que permite sólo encriptar el mensaje (la clave pública), y otra que permite desencriptarlo (la clave privada).
En el caso de la encriptación simétrica, hay que proteger la clave a toda costa ya que esta sirve para encriptar y desencriptar el mensaje, por tanto, de ser obtenida por un agente malicioso podría usarse para interceptar toda la comunicación.
La encriptación asimétrica, por otro lado, permite transferir la clave pública sin riesgo alguno, ya que no se puede desencriptar el mensaje sólo con esa clave.
La encriptación híbrida es un sistema criptográfico que encripta el mensaje con una llave simétrica y transfiere esa llave encriptada usando criptografía asimétrica.
Por lo tanto, para implementar esto, primero cliente y servidor se deben intercambiar la llave pública, y luego se intercambiarán las llaves simétricas usando las llaves públicas que se habían mandado primero.
La encriptación que se usa por defecto son AES-128 (encriptación simétrica) y RSA-1024 (encriptación asimétrica), aunque las longitudes de clave se puede cambiar.
<br>
\subsection key Intercambio de llaves
El intercambio de llaves es necesario para que los dos agentes en la comunicación, que de aquí en adelante serán referidos como <a href="http://es.wikipedia.org/wiki/Alice_y_Bob">Alice y Bob</a>, puedan enviarse los mensajes encriptados y luego puedan desencriptarlos al ser recibidos.
El protocolo es iniciado por Alice, que actúa de servidor:
-# Alice manda su llave pública RSA a Bob enviando una cadena de carácteres terminada en NULL ('\0').
-# Bob extrae uno uno los carácteres hasta encontrar un carácter NULL ('\0'), entonces obtiene la llave y la almacena para poder mandar los mensajes encriptados a Alice.
-# Bob manda su llave pública RSA a Alice de la misma forma, y ella la guarda exactamente igual que Bob.
-# Alice pasa a encriptar su llave AES con la llave de Bob y mandársela
-# Bob, lee la cantidad de bytes que representa un paquete de RSA de la longitud de llave predeterminada, por defecto 128 bytes, que contiene 86 bytes de datos desencriptados. Bob asume que la llave se ha transmitido en un sólo paquete<a href="#note1"><sup>[1]</sup></a><a name="cite1">.</a>
-# Bob hace exactamente lo mismo que alice con su llave AES
A partir de aquí, ambos ya pueden intercambiar mensajes encriptados.
<br>
\subsection send_crypt Envío/Recepción de mensajes encriptados
El protocolo es exactamente igual que en el caso sin encriptación, excepto que toda la comunicación pasa a ser encriptada con AES:
-# Bob le quiere mandar a Alice un mensaje, primero primero lo encripta y pone el número de carácteres (bytes) que ocupa el mensaje encriptado en forma de string, encripta el string con la longitud usando AES y lo manda.
-# Bob transmite el mensaje íntegro encriptado con AES.
-# Alice espera recibir un paquete de longitud del múltiple de menor tamaño de la llave AES, que como mínimo es 16, y dado que un int puede representar un máximo 4 GB de datos, asume que la longitud total del mensaje se puede expresar en esos 16 bytes de AES.
-# Alice pasa a desencriptar ese string para obtener la longitud del mensaje real encriptado y pasa a extraer exactamente los N bytes que ha leído que recibiría.
-# Alice desencripta el mensaje final.
<br>
<br>
\subsection plain Modo en texto llano
Este modo transmite los carácteres de texto sin ningún tipo de encriptación, por lo tanto son totalmente visibles para cualquier agente intermedio. Sin embargo, el modo sin encriptación es más rápido y ofrece el doble de velocidad de transferencia aproximadamente.
<br>
\subsection send Envío/Recepción de mensajes
El mensaje se transmite de la siguiente forma:
-# Bob le quiere mandar a Alice un mensaje, primero primero pone el número de carácteres (bytes) que ocupa el mensaje en forma de string terminado con carácter NULL ('\0') y lo manda.
-# Bob transmite el mensaje íntegro.
-# Alice lee uno a uno los carácteres del socket hasta encontrar un carácter NULL ('\0'), entonces lee lo que ha recibido, que es la longitud del mensaje real.
-# Alice pasa a extraer los N bytes que ha leído que recibiría y obtiene el mensaje final.
<br>
<br>
<br>
\section compile Compilación
A continuación se detallan las opciones e instrucciones necesarias para compilar esta librería.
<br>
\subsection defines Opciones de compilación
Los siguientes #defines establecen la configuración en tiempo de compilación
- \ref RSALENGTH : La longitud de la llave RSA que se usará.
- \ref AESLENGTH : La longitud de la llave AES que se usará.
- \ref CONFFILE : La ruta absoluta o relativa al fichero de configuración del servidor (véase: \ref conf).
- \ref PUBLICKEY : La ruta absoluta o relativa a la llave pública RSA. Existe en server.h y client.cpp
- \ref PRIVATEKEY : La ruta absoluta o relativa a la llave pública RSA. Existe en server.h y client.cpp
<br>
\subsection flags Flags de compilación y librerías
Flags de compilación necesarios:
- -I/carpeta/con/cabeceras_de/crypto++ -I/carpeta/con/cabeceras/de_la/librería/Socket
- -L/carpeta/con/la_librería/crypto++
- -lcryptopp -lpthread
Véase: \ref makefile
<br>
<br>
<br>
\section examples Ejemplos
A continuación se detalla el código para programar una aplicación servidor cliente sencilla
<br>
\subsection server Programar un servidor
Véase: \ref client_code
<br>
\subsection client Programar un cliente
Véase: \ref server_code
<br>
<br>
\section notes Notas
<a name="note1"><a href="#cite1">^</a>1. Esto es cierto sólo si la longitud de clave RSA es superior a 728 bits.</a>
*/