Introducción
============
Este es un pequeño apunte hecho con la idea de tener a manos algunos
conceptos sobre la comunicación segura mediante el protocolo TLS
especialmente en sistemas embebidos. Para cumplir ese objetivo,
vamos a comenzar por algunos conceptos básicos de criptografía,
y luego veremos como implementar parte de esto con la suite
OpenSSL (https://www.openssl.org/)
Por supuesto, y más a esta altura, este es un trabajo en desarrollo,
de tal manera que lo escrito aquí está sujeto principalmente al
aprendizaje futuro que se pueda hacer al llevar estos conceptos
a la práctica.
Algoritmos criptográficos
=========================
Hay dos tipos de algoritmos para encriptar, a saber:
1) Algoritmos de clave simétrica
En estos algoritmos se usa la misma clave para encriptar y para
desencriptar
2) Algoritmos de clave pública.
En estos algoritmos existen dos claves, una pública y otra privada.
La idea es que se usa una clave para encriptar y la otra para
desencriptar.
Sí Alice quiere comunicarse en forma segura con Bob, le manda su
clave pública. Bob la recibe y la usa para encriptar el mensaje
que le quiere enviar a Alice. Cuando Alice recibe el mensaje lo
desencripta con su clave privada. La clave pública no se puede usar
para desencriptar el mensaje.
Algoritmos usuales de encriptación asimétrica son RSA, DSA y ECDSA.
El último es el que produce con menos procesamiento niveles
aceptables de seguridad.
Intercambio de claves
El proceso anterior se puede usar para intercambiar claves de
algoritmos simétricos, que implican una carga de procesamiento menor
Alice envía su clave pública a Bob. Cuando la recibe, Bob la usa
para encriptar una clave de un algoritmo simétrico, y envía el
resultado a Alice. Ahora Alice, desencripta el mensaje con su clave
privada y puede comenzar a intercambiar mensajes con Bob usando
un algoritmo de clave simétrica.
Autenticación
Autenticar significa comprobar que quien manda el mensaje es quien
dice ser.
Una manera de autenticar es intercambiar el rol de las claves en un
algoritmo asimétrico. Es decir, que un mensaje cifrado con una clave
privada se pueda desencriptar con una clave pública.
La autenticación se produce porque la clave privada es una
"credencial" que sólo está en posesión de un ente determinado, de
tal manera que al recibir un mensaje cifrado con esa clave, se
garantiza su procedencia. (El uso de un determinada clave privada
se verifica al desencriptar el mensaje con la clave pública que
le corresponde).
3) Certificados digitales
Se usan para comprobar que una clave pública se corresponde con una
identidad determinada. Un certificado asocia una clave pública a
cierta identidad. Para asegurar esto, debe haber una tercera parte
que verifique esa correspondencia. Es decir, un ente confiable que
"de fe" que determinada clave pertenece a determinado ente.
A esta especie de "escribano" de lo denomina "Autoridad de
Certificación" (CA, Certificate Authority). Al igual que un
escribano, certifica la autenticidad de los datos del certificado
firmándolo, en este caso, con una firma digital.
Un formato estándard para los certificados se llama X.509
(Directory Authentication Framework)
El estándar X.509 define lo que debe estar en el certificado.
Esto incluye la identidad y la clave pública tanto del emisor
como del propietario del certificado y el intervalo de validez.
Digest
Un digest es un campo calculado incluido en el certificado
especificado en el estándar X.509. El digest es una especie
de 'checksum' calculado sobre todos los demás campos del
certificado mediante una función llamada 'hash'. La longitud del
'digest' es fija. La idea es que dos entradas diferentes en la
función hash van a resultar en digests diferentes, y por otro lado,
tampoco puede deducirse el mensaje partiendo del digest.
Firma digital
La autoridad de certificación (CA) toma el digest calculado a partir
de los campos del certificado. y lo encripta usando su clave
privada. Esto permite al que recibe el certificado, desencriptar
el digest con la clave pública de la CA (lo cual indica a su vez
que fue firmada por ella) y compararlo con una copia calculada
localmente (ya que la función hash es pública).
Si el valor del digest desencriptado y coincide con el valor del
que se calcula localmente, se puede asumir que
a) la firma de la CA es auténtica y
b) los campos del certificado no han sufrido modificaciones
indebidas.
4) Funciones de hash
Son funciones de hash usuales MD5, SHA1 (ahora considerada insegura)
y SHA256.
Para agregar un nivel más de integridad al digest, se suelen usar
funciones hash que admiten el uso de una clave compartida por el
emisor y el receptor, de tal manera que no se pueda revelar el
checksum si no se conoce esa clave. Un digest creado de esta manera
se llama Message Authentication Code (MAC).
6) El protocolo TLS
Deriva del SSL desarrollado por Netscape a principios de los años
90. TLS significa Transport Layer Security (Seguridad en la capa
de transporte)
La meta principal de TLS es mantener la privacidad y la integridad
de los datos que se comunican.
Privacidad: todo el intercambio de información entre el cliente y
el servidor se realiza encriptada mediante algún algoritmo de clave
simétrica. Esta clave es única para cada conexión, y es
intercambiada mediante encriptación asimétrica.
Confiabilidad: Todos los mensajes encriptados incluyen un digest
en la forma de un MAC ( Message authentication code) con clave. El
texto plano no incluyen digests pero son validados antes que se
envíen los datos de la aplicación (?).
Identificación: ambas partes (peers) pueden requerir que su
contraparte se identifique. La identificación se lleva a cabo por
medio de certificados firmados digitalmente.
Open SSL
========
Introducción
OpenSSL es una suite que nos va a permitir tanto crear, como firmar
y gestionar certificados, ya sean del lado del servidor (PC) como
del lado del cliente (sistema embebido)
La idea es comenzar creando una Autoridad de Certificación (el
ente confiable del que hablábamos antes) propia, lo cual nos
permitirá firmar y gestionar nuestros propios certificados.
Una vez que la Autoridad de Certificación está seteada, haremos
los certificados que sean necesarios, tanto para el servidor como
para cada uno de los clientes.
Antes de poder crear una Autoridad de Certificación se deben tener
a la mano algunos datos y tomar algunas decisiones.
a) Se debe elegir un algoritmo para realizar el hash del digest,
por ejemplo MD5, SHA-1, SHA-256 (* este es preferible), etc
b) Se debe elegir un algoritmo para firmar el digest, por ejemplo
RSA, DSA, ECC (* ECC de 224 bits es suficiente). Al seleccionar
uno de estos algoritmos (RSA, ECC, etc) toda la cadena de
certificados se firma con el algoritmo elegido.
c) Para construir el certificado son necesarios los siguientes datos
- Tamaño de la clave (pe. 2048)
- Algoritmo de hash (pe. SHA256)
- Tiempo de validez del certificado en días (pe. 3650)
- País
- Provincia
- Nombre de la organización (pe. nombre de la empresa)
- Unidad de la organización
- Nombre del certificado (pe. Mi certificado raíz)
- Correo electrónico (pe.
[email protected])
Una vez creado e instalado el certificado de la CA (root), se
puede comenzar a crear y firmar los nuevos certificados
Nota: Para poder probar los certificados con cualquier otro nombre
que no sea 'localhost' se deben agregar las correspondientes
entradas en el archivo '/etc/hosts'. Por ejemplo
127.0.0.1 www.miempresa.com
127.0.0.1 LaHeladeraDeCasa
Usar OpenSSL
OpenSSL se usa para crear y firmar certificados, para crear las
autoridades de certificación, para crear las claves, para crear las
solicitudes de certificación (...)
Para crear un certificado desde cero tenemos que seguir estos pasos
- Instalar OpenSSL (por lo general, viene preinstalado en Linux)
- Crear una estructura de directorios, para almacenar claves,
solicitudes de firma, certificados, etc.
- Crear un archivo de configuración personalizado de acuerdo a
nuestras necesidades, porque en caso contrario, se usará el
del sistema, que por lo general no nos servirá.
a) Crear la estructura de directorios
Lo primero es crear una estructura de directorios para mantener
los archivos y los datos necesarios para la CA
mkdir openssl
cd openssl
mkdir raiz-ca
cd raiz-ca
mkdir certs db private
chmod 700 private
touch db/index
openssl rand -hex 16 > db/serial
echo 1001 > db/crlnumber
Directorios
raiz-ca/: Un directorio para tener todo en un lugar, por sí hay
que borrar y empezar de nuevo.Se puede llamar de cualquier
manera
certs/: Almacenamiento de certificados; los nuevos certificados
se colocarán aquí a medida que se emitan.
db/: Este directorio se usa para la base de datos de
certificados (índice) y los archivos que contienen el próximo
certificado y números de serie de CRL. OpenSSL creará algunos
archivos adicionales en tanto sean necesarios.
private/: Este directorio almacenará las claves privadas, una
para la CA y la otra para el responder OCSP. Es importante que
ningún otro usuario tenga acceso a este directorio. (De hecho,
sí el trabajo de CA se va a tomar seriamente, la máquina en la
que se almacena el material de raíz (root) debe tener solo un
número mínimo de cuentas de usuario).
Nota: Al crear un nuevo certificado de CA, es importante
inicializar los números de serie de los certificados con un
generador de números aleatorios, como se hace aquí. Esto es muy
útil si alguna vez termina creando e implementando múltiples
certificados de CA con el mismo nombre distinguido
(común si se comete un error y se necesita comenzar de nuevo);
Se evitarán conflictos porque los certificados tendrán
diferentes números de serie.
b) Editar el archivo de configuración
Luego hay que editar el archivo de configuración que se dará
como entrada al comando 'req' de openssl, por ejemplo
raiz-ca.conf (Este archivo va por separado)
c) Crear la Autoridad de Certificación (CA)
Crear una CA implica crear una clave raíz (pe. raiz-ca.key.pem)
y un certificado raíz (pe. raiz-ca.cert.pem), de tal manera
que vamos a hacer las dos cosas por separado.
1) Crear la clave raiz (Pass: 'Pirulo2050')
openssl ecparam -name secp384r1 -genkey | openssl ec \
-aes-256-cbc -out raiz-ca/private/raiz-ca.key.pem
Este comando es en realidad dos, que se unen mediante una
tubería. La primera parte (a la izquierda del '|' ) es
'openssl ecparam -name secp384r1 -genkey '
utiliza la curva secp384r1 para generar una clave (-genkey)
de curva elíptica.
La segunda parte del comando (a la derecha del '|') toma la
clave generada recién, la cifra usando el cifrador
aes-256-cbc y la guarda encriptada en el archivo raiz-ca.key.pem.
Notar que el comando 'ec' es el que precesa las claves de
curva elíptica.
Tanto la curva elíptica como el cifrador usado para encriptar
pueden elegirse dentro de todos los que ofrece openssl. Sin
embargo, la curva 'secp384r1' se elige porque es una de las que
mayor soporte tiene entre los navegadores, de modo que es de
uso muy común.
Al ejecutar el comando nos va a pedir una clave, debido a que
lo estamos encriptando con 'aes-256-cbc'. Hay que recordar esta
clave, porque la vamos a necesitar cada vez que accedamos a ese
archivo, por ejemplo, al ejecutar el comando 'req'.
Finalmente se ponen los permisos adecuados al archivo que
contiene la clave
chmod 400 raiz-ca/private/raiz-ca.key.pem
2) Hacer el certificado
La idea ahora es hacer el certificado autofirmado, puesto
que nadie puede firmar el certificado de una CA raiz, más que
ella misma.
luck@mini:~/openssl$ cd raiz-ca/
openssl req -config raiz-ca.conf -extensions ca_ext \
-key private/ca.key.pem -new -out certs/raiz-ca.cert.pem \
-x509 -days 7300
Notar los switchs
'-key': especifica el archivo desde el cual se lee la clave
privada.
'-out': especifica el archivo en el cual se escribirá la
salida. Por defecto la salida se escribe a la salida estándar.
'-extensions ca_ext': apunta a la sección del
archivo de configuración (raiz-ca.conf en este caso) en donde se
define la autoridad de certificación. (En el archivo
raiz-ca.conf, en la sección [ca_ext] se definen las
características de la autoridad de certificación)
'-x509': este switch da un certificado auto firmado, en
lugar de un CSR (Solicitud de firma de certificado). Cualquier
extensión se especifica en el archivo de configuración. Salvo
que se especifique un numero de serie con el comando
'set_serial', se utiliza un número aleatorio grande como número
de serie.
'-days n'; se usa junto con -x509, y especifica los días
de validez del certificado. Por defecto son 30 días.
'-new': esta opción es la que genera un nuevo requerimiento
de certificado, y pregunta al usuario por losvalores
pertinentes. Los campos para los cuales se pregunta al usuario
junto con sus valores máximos y mínimos son especificados en
el archivo de configuración y en cualquier extensiómn requerida.
Si no se usa la opción '-key' se generará una nueva clave RSA
privada usando la información especificada en el archivo de
configuración.
Para más datos sobre el comando req se puede visitar la página
manual de la documentación oficial:
https://www.openssl.org/docs/man1.0.2/apps/req.html
Ahora, hay que ver lo que quedó dentro del certiicado para
asegurarnos de que es correcto.
luck@mini:~/openssl/raiz-ca$ openssl x509 -noout -text \
-in certs/raiz.cert.pem
y acá debe aparecer en el terminal una representación del
certificado. Debemos ver:
Vencimiento: dentro de 20 años
Algoritmo de firma: ecdsa-with-SHA256
Longitud d eclave pública: 384 bit
CA:TRUE
3) Crear la clave del cliente, y la solicitud de firmado (CSR)
En el directorio raiz-ca ponemos
openssl ecparam -name secp384r1 -genkey | openssl ec \
-aes-256-cbc -out private/test1.key.pem
(Pass: 'Cliente2050')
Hacemos la CSR
luck@mini:~/openssl$ openssl req -config raiz-ca/raiz-ca.conf \
-new -key raiz-ca/private/test1.key.pem \
-out raiz-ca/certs/test1.csr.pem
(Notar que no aparece el switch '-x509', porque hay que se trata
de obtener una CSR)
El archivo con la solicitud de certificación (CSR) está ahora
en csr/test1.csr.pem
4) Firma
luck@mini:~/openssl/raiz-ca$ openssl ca -config raiz-ca.conf \
-extensions ext_client -notext -in certs/test1.csr.pem \
-out certs/test1.cert.pem
'ca' es el comando que se usa para firmar certificados y es una
aplicación mínima de autoridad de certificación. Además de
para firmar certificados, se puede usar para hacer CRL (listas
de rechazo de certificados) y para mantener una base de datos en
modo texto de los certificados emitos y de su estado.
Los switches usados son
'-in' se usa para indicar el nombre del archivo que contiene
un solo requerimiento de firma
'-notext' no escribe texto a la salida especificada
'-out' indica el nombre del archivo sobre el cual saldrá el
certificado. Por defecto se usa la salida estándar. Los detalles
del certificado se escribirán en este archivo en formato PEM,
salvo que se especifique el formto DER con la opción -spkac
Apéndice
========
Suites de cifrado
Las suites de cifrado de OpenSSL incluyen algoritmos para
* Intercambio de claves
* Autenticación
* Cifrado
* Verificar integridad
Para saber cuáles son los grupos de cifradores soportados por
OpenSSL se usa el comando
$ openssl ciphers -v 'ALL:COMPLEMENTOFALL'
que ejecutada da algo como
luck@mini:~/prueba$ openssl ciphers -v 'ALL:COMPLEMENTOFALL'
ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD
ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256)
Mac=AEAD
ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA384
ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA384
ECDHE-RSA-AES256-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA1
ECDHE-ECDSA-AES256-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA1
SRP-DSS-AES-256-CBC-SHA SSLv3 Kx=SRP Au=DSS Enc=AES(256) Mac=SHA1
SRP-RSA-AES-256-CBC-SHA SSLv3 Kx=SRP Au=RSA Enc=AES(256) Mac=SHA1
SRP-AES-256-CBC-SHA SSLv3 Kx=SRP Au=SRP Enc=AES(256) Mac=SHA1
[...]
La información que da el comando está ordenada en columnas que
significan lo siguiente, de izquierda a derecha:
1 - Nombre de la suite en OpenSSL: Bajo este nombre se puede hacer
referencia a la suite de cifrado bajo OpenSSL
2 - Versión de TLS a partir del cual está soportado
3 - Algoritmo de encriptado de clave (pe. ECDH): Es el que se usa para
intercambiar las claves que se usarán para encriptar toda la
comunicacón.
4 - Algoritmo de autenticación (pe. ECDSA): Este es el algoritmos
de clave asimétrica que se usa para comprobar las identidades. Es
el que se us para encriptar el digest
5 - Algoritmo de encriptado (pe. AES): Este es el algoritmo que se usa
para cifrar la comunicación
6 - Algoritmo de verificación de integridad (pe. HMAC-SHA1): Este es el
algoritmo que se usa para calcular el digest
Elliptic Curve Digital Signature Algorithm (ECDSA), es una modificación
del algoritmo DSA que emplea operaciones sobre puntos de curvas
elípticas en lugar de las exponenciaciones que usa DSA (problema
del logaritmo discreto). La principal ventaja de este esquema es
que requiere números de tamaños menores para brindar la misma
seguridad que DSA o RSA. Existen dos tipos de curvas dependiendo del
campo finito en el que se definan, que pueden ser GF(P) o
GF(2exp(m)).
(fuente: https://es.wikipedia.org/wiki/ECDSA )
Advanced Encryption Standard (AES) también conocido como Rijndael
(pronunciado "Rain Doll" en inglés), es un esquema de cifrado por
bloques adoptado como un estándar de cifrado por el gobierno de los
Estados Unidos. Desde 2006, el AES es uno de los algoritmos más
populares usados en criptografía simétrica"Rijndael".
(fuente: https://es.wikipedia.org/wiki/Advanced_Encryption_Standard )
Elliptic-curve Diffie–Hellman (ECDH), es un protocolo anónimo para el
acuerdo de claves, que permite a dos partes, cada una con un par de
claves publica - privada de curvas elípticas, establecer un secreto
compartido sobre un canal inseguro. Este secreto compartido se
puede usar directamente como clave, o para derivar otra clave. La
clave, o la clave derivada pueden ser usadas para encriptar la
comunicación subsecuente usando un cifrador de clave simétrica.
Este protocolo es una variante del protocolo de Diffie Hellman que
usa criptografía de clave elíptica.
(fuente https://en.wikipedia.org/wiki/Elliptic-curve_Diffie
%E2%80%93Hellman )
Hash-based message authentication code (HMAC), sgnifica código de
autenticación de mensajes basado en hash. Es un tipo específico
de código de autenticación de mensajes (MAC), que involucra una
función de hash criptográfica y una clave criptográfica secreta.
Puede usarse tanto para verificar la integridad como la autenticidad
de un mensaje, del mismo modo que con cualquier hash. Se pueden
usar funciones hash como MD5 o SHA1, para calcular un HMAC; el
algoritmo resultante se llama entonces HMAC-MD5 o HMAC-SHA1.
(fuente: https://en.wikipedia.org/wiki/Hash-
based_message_authentication_code )
5) Certificados y sus codificaciones
(fuente: http://www.gtopia.org/blog/2010/02/der-vs-crt-vs-cer-vs-pem-
certificates/)
Las codificaciones de los certificados se suelen denotar por las
extensiones de los archivos respectivos y constituye una buena
práctica hacerlo.
Extensiones y codificaciones
.der es una extensión que se usa para denotar un certificado
codificado bajo el formato binario DER. Estos archivos también
pueden tener la extensión CER o CRT. Correctamente se los debe
llamar "certificados codificados en formato binario DER" y no
"certificados DER".
.pem es una extensión usada para denotar un certificados u
otro tipo de documentos con datos estructurados bajo
ASCII (base 64). Estos documentos comienzan con una
línea "---BEGIN---"
Otras extensiones comunes
.crt es una extensión que se usa para indicar que el archivo
es un certificado. Este archivo, no obstante, puede estar codifcado
bajo PEM o DER. La extensión .der, entonces, se suele agregar a
la extensión .pem o .der dando nombres como prueba.crt.pem. Esta
extensión es común en los istemas tipo UNIX.
.cer es una forma alternativa de indicar lo mismo que en UNIX
indica la extensión .crt, pero para los operativos de Microsoft.
Lo mismo que antes, pueden estar tanto codificados bajo formatos
PEM o DER.
.key es una extensión que indica que el archivo contiene una
clave pública o privada del tipo PKCS#8. De nuevo, esta clave
puede estar codificada en formato PEM o DER. Un nombre de archivo
de clave codificada en formato PEM podría ser prueba.key.pem.
Operaciones comunes sobre certificados de OpenSSL
Hay cuatro operaciones básicas que pueden hacerse con OpenSSL
sobre los certificados a saber: vista, transformación, combinación
y extracción.
Vista
Vista de un certificado codificado PEM
Aunque los certificados codificados bajo formato PEM están
escritos en ASCII no se pueden leer, así que se tiene que usar una
utilidad para el caso
openssl x509 -in cert.pem -text -noout
Transformación
La operación de transformación permite pasar de una
codificación a otra, por ejemplo de PEN a DER
PEM a DER: openssl x509 -in cert.crt -outform der -out cert.der
DER a PEM: openssl x509 -in cert.crt -inform der -outform pem \
-out cert.pem
Combinación
A veces conviene combinar dos certificados en uno, como por
ejemplo, en el caso que se quiera poner una clave pública y una
privada en un mismo certificado.
Una forma sencilla de hacer esto es pasar los dos certificados a
formato PEM (ASCII base 64) y luego copiar los dos en un archivo
nuevo.
Extracción
Algunos certificados pueden ser una combinación de varias cosas.
Por ejemplo, un archivo podría combinar cosas como: un certificado,
una clave pública, una clave privada, un certificado firmado, un
certificado de una autoridad de certificación, y /o una cadena de
autoridad.
Glosario
========
CRL: Certificate Revocation List
OCSP: Online Certificate Status Protocol
CSR: Certificate Signing Request
========================================================================
Bookmarks
========================================================================
*** Explicación de los certificados y de OpenSSL ***
https://access.redhat.com/documentation/en-
US/Fuse_ESB/4.4.1/html/Web_Services_Security_Guide/files/ManageCerts.html
-0-
*** Explicación de formatos DER y PEM, conversión, etc. ***
http://www.gtopia.org/blog/2010/02/der-vs-crt-vs-cer-vs-pem-certificates/
-0-
*** Links indispensables para claves de curvas elípticas! ***
https://medium.com/where-the-flamingcow-roams/elliptic-curve-certificate-
authority-bbdb9c3855f7
https://jamielinux.com/docs/openssl-certificate-authority/create-the-root-
pair.html
https://wiki.openssl.org/index.php/Command_Line_Elliptic_Curve_Operations
-0-
*** Explicación general de TLS orientada a sistemas embebidos ***
Fuente: https://realtimelogic.com/blog/2014/05/How-to-act-as-a-Certificate-
Authority-the-Easy-Way