criptografia
DESCRIPTION
tipos de mecanismos criptograficos, Firma digital, Criptografía simétrica y asimetrica.TRANSCRIPT
No cabe duda de que los últimos tiempos están marcados por un nivel de paranoia adicional en cuanto a la vigilancia, la seguridad y privacidad de nuestra información. Ahí están la NSA, Snowdeny toda una plétora de fallos de seguridad en importantes librerías, aplicaciones y dispositivos que (intencionados o no), nos recuerdan que siempre deberíamos de poner un poco de cuidado adicional cuando de lo que se trata es de crear aplicaciones seguras, y más aún si estas están circunscritas al ámbito web.
Precisamente para ayudarnos en esas tareas tenemos a nuestra disposición la capacidad de cifrar la información, aplicar firmas digitales, o bien generar huellas únicas para un conjunto dado de datos mediante una amplia variedad de algoritmos y sistemas criptográficos. Y si te interesa el tema, he de recomendarte un par de libros que, en mi opinión, son esenciales: "Cryptography Engineering: Design Principles and Practical Applications" (Niels Ferguson, Niels, Schneier, Bruce and Kohno, Tadayoshi y "Applied Cryptography: Protocols, Algorithms, and Source Code in C" (Schneier, Bruce).
Hash y RSA fácil
Ahora bien, como en otras tantas cosas, el enfoque propuesto por Xojo es el de facilitarnos al máximo y a un punto realmente transparente todas las operaciones que, por otra parte, podrían resultar un tanto farragosas o requerir de unos conocimientos elevados. (Recuerda que la filosofía de Xojo es la de poner las herramientas de programación al alcance de cualquier usuario, al tiempo que los desarrolladores avanzados encuentren también herramientas y características potentes que les permita crear todo tipo de aplicaciones.)
Así, a partir de la versión Xojo 2013r4.1 (diciembre de 2013) encontramos en el lenguaje un completo conjunto de funciones criptográficas basadas en la librería Crypto++ 5.6.2 donde se exponen para su uso en aplicaciones multiplataforma (WIndows, OS X, Linux y Web) los algoritmos de Hash o huellas únicas correspondientes a MD5 y SHA en sus variantes SHA1, SHA256 y SHA512, diseñadas por la NSA por cierto.
En cuanto a funciones criptográficas encontramos a nuestra disposición el popular sistema criptográfico RSA, con las capacidades de generación del par de claves publica/privada precisadas para el cifrado y firma de información, así como en las operaciones opuestas de conversión a texto claro y verificación de datos firmados; además de las funciones que permiten realizar precisamente todas estas tareas: cifrado, descifrado, firma, verificación de firma, y también la capacidad de verificar una clave. De hecho, siempre deberíamos de verificar la validez de una clave pública antes de su uso en el cifrado de los datos que queramos enviar al destinatario propietario de la misma, por ejemplo.
Si bien lo anterior es el plato fuerte en cuanto a las funciones disponibles bajo el módulo Crypto, también encontraremos la función HMAC que permite crear un código de autenticación de mensaje o, dicho de otro modo, una función Hash con esteroides en las que se utilizará el sistema de Hash que le indiquemos en combinación con una clave de nuestra cosecha.
Precisamente para generar esa clave adicional de la función HMAC (o 'salt'), Xojo proporciona la función GenerateRandomBytes y cuya finalidad no puede ser más descriptiva. De hecho, el único parámetro de entrada no es otro sino un entero mediante el cual indicaremos el tamaño de salida, mientras que el producto será lo que en Xojo se denomina un MemoryBlock y que no es más que un buffer de memoria mediante el que podemos trabajar con los datos en bruto, sin estar envueltos bajo una estructura determinada (por supuesto, en Xojo encontraremos múltiples métodos de clase para convertir desde y hacia MemoryBlocks los datos correspondientes a las estructuras internas de dichas clases, como pueda ser el texto).
Ahora bien, en su estado actual Xojo no expone muchos otros esquemas y algoritmos presentes en la librería Crypto++ 5.6.2, cosa aparte es que internamente pueda utilizar alguno de ellos. Quizá una de las ausencias más notables sea el esquema de criptografía de curva elíptica. Quizá es cuestión de tiempo que la veamos implementada en Xojo, junto con algunas otras ausencias notables.
Aun así, con lo disponible cualquier usuario puede encontrar la respuesta a las principales necesidades en cuanto al cifrado y verificación de datos, así como en el típico almacenamiento y posterior verificación en las contraseñas u otra información de carácter sensible, especialmente cuando se utiliza Xojo Web o Xojo Pro para la creación de aplicaciones con despliegue web, o incluso Xojo Pro en la creación de aplicaciones de servidor autónomas donde la seguridad en el intercambio de la información sea un requerimiento fundamental.
RSA en la práctica
¿Y cuán sencillo resulta aplicar todo lo anterior? Pues lo cierto es que sorprendentemente fácil, tanto por el diseño de las propias funciones como por el lenguaje Xojo en general.
Por ejemplo, la creación del par de claves Pública/Privada que supone el punto de partida para utilizar el resto de funciones RSA es tan simple como utilizar el siguiente código, y del que estoy convencido que podrás entender perfectamente incluso en el caso de que esta sea tu primera exposición al lenguaje de programación Xojo.
Crypto.RSAGenerateKeyPair ( Bits As Integer, ByRef PrivateKey As String, ByRef PublicKey As String ) As Boolean
En el parámetro Bits pasaremos como número entero la longitud de la clave, donde los valores típicos suelen ser 1.024 o 2.048.
Sobre el resto, se utilizan dos parámetros de tipo String (cadena) y que serán los responsables de contener tanto la clave pública como la privada. Aquí, se utiliza la partícula 'ByRef' de Xojo para indicar que el parámetro se pasará como referencia y no como valor (es decir, como copia), de modo que se pueda modificar desde dentro de la función el contenido del objeto apuntado por la variable.
Por último, la función devolverá un booleano donde se indicará mediante el valor 'True' que se ha podido realizar la operación con éxito o 'False' en caso contrario.
Por tanto, un fragmento de código que nos permitirá crear ambas claves y cifrar a continuación un mensaje determinado sería el siguiente:
Dim clavePrivada As String Dim clavePublica As String
If Crypto.RSAGenerateKeyPair( 1024, clavePrivada, clavePublica ) Then
Dim buffer As New MemoryBlock(15) buffer.StringValue(0, 15) = "Mensaje cifrado"
Dim cifrado As MemoryBlock = Crypto.RSAEncrypt( buffer, clavePublica )
if cifrado <> nil then
MsgBox cifrado.StringValue(0,15)
dim descifrado as MemoryBlock = Crypto.RSADecrypt(cifrado, clavePrivada)
MsgBox descifrado.StringValue(0,15)
End If
End If
Una vez cifrado, sólo es necesario utilizar a continuación la clave privada para volver a convertirlo en texto claro.
Ahora bien, una particularidad de trabajar con bloques de memoria es que desaparece toda la información de codificación asociada con el texto (por ejemplo UTF-8), de modo que es preciso tenerlo en cuenta a la hora de volver a recuperar dicha información otra vez desde un bloque de memoria que hayamos descifrado.
Acceso a Llaveros
También hay que tener en cuenta que si bien el módulo Crypto incluye todas las funciones necesarias para cifrar, firmar o generar huellas digitales de nuestra información, depende de nosotros poner a buen recaudo las claves privadas que generemos.
Existen muchas formas de hacerlo, y de hecho no debería de suponer ningún problema mediante las clases incluidas en el framework de Xojo. Ahora bien, los usuarios de OS X lo tienen aun un poco más sencillo gracias a que Xojo incluye soporte para la característica Acceso a Llaveros (Keychain) mediante la que se facilita sobremanera el guardado y recuperación de contraseñas utilizadas por las aplicaciones.
Qué son y para qué sirven los hash?: funciones de resumen y firmas digitales
Los hash o funciones de resumen son algoritmos que consiguen crear a partir de una entrada (ya sea un texto, una contraseña o un archivo, por ejemplo) una salida alfanumérica de longitud normalmente fija que representa un resumen de toda la información que se le ha dado (es decir, a partir de los datos de la entrada crea una cadena que solo puede volverse a crear con esos mismos datos).
Estas funciones no tienen el mismo propósito que la criptografía simétrica y asimétrica, tiene varios cometidos, entre ellos está asegurar que no se ha modificado un archivo en una transmisión, hacer ilegible una contraseña o firmar digitalmente un documento
Características de los hash
En definitiva las funciones hash se encargan de representar de forma compacta un archivo o conjunto de datos que normalmente es de mayor tamaño que el hash independientemente del propósito de su uso.
Este sistema de criptografía usa algoritmos que aseguran que con la respuesta (o hash) nunca se podrá saber cuales han sido los datos insertados, lo que indica que es una función unidireccional. Sabiendo que se puede generar cualquier resumen a partir de cualquier dato nos podemos preguntar si se podrían repetir estos resúmenes (hash) y la respuesta es que teóricamente si, podría haber colisiones, ya que no es fácil tener una función hash perfecta (que consiga que no se repita la respuesta), pero esto no supone un problema, ya que si se consiguieran (con un buen algoritmo) doshash iguales los contenidos serían totalmente distintos.
Ejemplos y formas de uso
Las funciones hash son muy usadas, una de las utilidades que tiene es proteger la confidencialidad de una contraseña, ya que podría estar en texto plano y ser accesible por cualquiera y aún así no poder ser capaces de deducirla. En este caso, para saber si una contraseña que está guardada, por ejemplo, en una base de datos es igual a la que hemos introducido no se descifra el hash (ya que debería de ser imposible hacerlo) sino que se aplicará la misma función de resumen a la contraseña que especificamos y se comparará el resultado con el que tenemos guardado (como se hace con las contraseñas de los sistemas Linux).
Pongamos un ejemplo, la función hash MD5 es una de estas funciones de resumen y la usaremos para resumir el siguiente texto:
Genbeta Dev
Y aplicaré la función de resumen con el comando especifico que tienen la mayoría de sistemas basados en Linux (md5sum):
pedro@ubuntu:~$ md5sum
Genbeta Dev
b71dada304875838f0263e3ae50c2c49 -
Por lo que la última línea es la del hash, que podéis comprobar en un terminal, en una herramienta online o con una aplicación con este fin, aunque se puede aplicar en muchos lenguajes de programación que lo implementan (no solo esta función, sino también otros tipos como el SHA que puede admitir distinta longitud).
Asegurar la integridad de la información
Otro uso que tiene esta función es la de garantizar la integridad de los datos y es algo que habréis visto muchas veces, por ejemplo en algunas webs que proporcionan descargas de archivos grandes, por ejemplos software, dando junto a su vez el resumen del archivo y la función usada.
Por poner un ejemplo en la página de descarga de Virtual Box podemos encontrar esta página con todos los resúmenes de las descargas disponibles con los que podemos comprobar que el archivo se ha descargado correctamente y que nadie ha modificado su contenido durante la transmisión.
Para poner en práctica este uso cogeré esta imagen de HTML5 y le aplicaré una función de resumen con el algoritmo MD5.
Y el resultado de hacer el resumen es el siguiente, usando otra vez la función presente en sistemas Linux (md5sum).
pedro@ubuntu:~$ md5sum HTML5.png
cc617bf6a1ec75373af6696873fccef1 HTML5.png
Este es el método para saber que un documento está integro tras su recepción, por eso se usa para comprobar que un archivo se a descargado correctamente o para comprobar que datos como un pequeño texto sigue siendo el mismo tras su emisión.
Firma digital
Firmar un documento no es algo novedoso, pero la firma digital si lo es un poco más y nos ayuda a verificar la identidad del emisor de un mensaje (así nos podemos asegurar que nuestro jefe nos manda un archivo concreto y no es el vecino que nos gasta una broma).
El método más simple de firma digital consiste en crear un hash de la información enviada y cifrarlo con nuestra cave privada (de nuestro par de claves de la criptografía asimétrica) para que cualquiera con nuestra clave pública pueda ver el hash real y verificar que el contenido del archivo es el que hemos mandado nosotros.
Me voy a adelantar al próximo capítulo sobre criptografía y hablaré un poquito de GnuPG (GPG) que es una herramienta de cifrado que nos permite firmar documentos, en este caso lo haré con una firma en texto plano (es un sistema menos seguro pero veremos que es lo que hace).
Lo que voy a hacer es firmar la imagen que hemos usado antes (la de HTML5) con el siguiente comando en una terminal de Linux (para otras plataformas hay otras soluciones muy similares o incluso idénticas):
pedro@ubuntu:~$ gpg --clearsign HTML5.png
Necesita una frase contraseña para desbloquear la clave secreta
del usuario: "Pedro Gutiérrez Puente (Clave pública) <[email protected]>"
clave DSA de 3072 bits, ID 783F3E6D, creada el 2012-12-11
Automáticamente a partir del archivo HTML5.png nos genera el archivo HTML5.png.asc que si lo abrimos con un visor de texto vemos el contenido de la imagen (un conjunto de caracteres sin sentido) y al final del archivo el siguiente texto (que contiene el hash cifrado):
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
iF4EAREIAAYFAlD0vH0ACgkQJQ5Gcng/Pm1gDgD+PnXZfni9n90duv2ir0hdnWdp
1bpBHGzCNWxN8q5I8CoA/RsdMeMxY9kwOx/y8jnxQYDjWFiBRThiE7GSxTtvXUPf
=PwS6
-----END PGP SIGNATURE-----
Resumen
Junto con este artículo sobre los hash tenemos el que habla sobre los tipos de criptografía (simétrica y asimétrica) que son la base para comprender el siguiente y último de la serie sobre criptografía, donde pondremos en práctica estos conceptos junto a GPG.
¿Qué es y como surge la criptografía?: un repaso por su historia
La criptografía es una necesidad derivada de realizar comunicaciones por escrito (en su
origen)creada para preservar la privacidad de la información que se
transmite, garantizando que una persona que no esté autorizada no pueda leer el
contenido del mensaje.
En la historia hemos tenido multitud de ejemplos de formas de encriptar mensajes como
los métodos espartanos de hace 2.500 años, el cifrado de Polybios (de los griegos) o
el cifrador del César (de los romanos), y sin olvidarnos de la máquina de encriptación
más famosa de la historia: la máquina Enigma.
Historia de la criptografía
En este artículo voy a tratar solamente de la historia de la criptografía y pondré unos
ejemplos prácticos, posteriormente me adentraré en los distintos tipos de criptografía
moderna y posteriormente su uso.
La escítala espartana (siglo V a. C.)
Los primeros mensajes cifrados que conocemos datan del siglo V antes de Cristo, de
procedencia espartana, que ponían en práctica un método simple y rudimentario que
consistía en coger una vara (llamada escítala), se le enroscaba una cinta de cuero o
papiro y posteriormente se escribía de forma longitudinal (como en la imagen).
Y por último se desenrollaba la cinta, con un puñado de letras sin sentido y se mandaba a
través del seur mensajero de turno al trote.
Supuestamente solo se podía desencriptar la información con una vara del mismo
diámetro que la original sobre la que se escribió (obviamente si te pones a intentar
cuadrar las letras acabas sacando algo en claro, pero en la época no se sabía demasiado
leer, tampoco el idioma origen y mucho menos tenían la cultura general necesaria para
pensar que la información estaba encriptada).
Uso
El diámetro de la escítala es la clave de este método de encriptación (o simplemente cada
cuantos caracteres empieza una vuelta).
En el ejemplo encriptaremos la siguiente entrada de texto:
Genbeta Dev – Historia de la criptografía – Método usado por los espartanos
Y como clave o diámetro de la escítala (n) tomaremos el número 7, es decir, en cada
vuelta de la cinta enroscada en el la vara pondremos 7 caracteres.
El resultado es el siguiente:
G tMose-doé pn egtpabH rooreiladrttsafo aat í ln ocauooDrr ssseii-a vap de
Podéis poner la técnica en marcha con este ejemplo que he realizado y el
código JavaScript es el siguiente:
function escitala(txt,n){
//Convertimos "n" en entero
var n=Math.floor(Number(n))
//"e" nos indica si entra justo en las filas
var e=(txt.length%n>0?1:0)
//Calculamos el número de filas resultantes
var lin=Math.floor((txt.length/n)+e)
//"r" contiene la respuesta
var r=''
//Añadimos el carácter a la respuesta
for(var a=0;a<lin;a++) for(var b=0;b<n;b++)
r+='<span>'+txt.charAt(a+(b*lin))+'</span>'
return r
}
La función necesita dos argumentos, el texto y el diámetro que usaremos de clave (n) de
la siguiente forma: escitala([Texto],[Entero: diámetro]).
El cifrador de Polybios (siglo II a. C.)
Este sistema es el primer cifrado por sustitución de caracteres. Se atribuye la invención a
el historiador griego Polybios y el sistema de cifrado consiste en sustituir un carácter por
el numero o letra de una columna o fila (como si jugásemos al hundir la flota).
En el ejemplo de este sistema introduciremos la siguiente cadena:
Genbeta Dev Historia de la criptografia Metodo usado por los griegos
Nota: tenemos que tener en cuenta que en este método se sustituye la letra “J“ por la
“I“.
El resultado de encriptar con la tabla de la imagen (la teóricamente real) es el siguiente:
BBAECCABAEDDAA ADAEEA BCBDDCDDCDDBBDAA ADAE CAAAACDBBDC
EDDCDBBDBAABABDAA CBAEDDCDADCD DEDCAAADCD CECDDB CACDDC
BBDBBDAEBBCDDC
Y podéis probarlo con este ejemplo para encriptar y desencriptar con el sistema griego
(Polybios).
var let='abcdefghiklmnopqrstuvwxyz'
var tra='ABCDE'
//función de encriptación
function polybios_enc(txt){
//Comprobamos que el texto es válido
var pat=/^[0-9A-z\s]*$/
if(!pat.test(txt)) return 'Texto no válido'
//Lo pasamos a minúsculas y convertimos la "j" en "i" (como
requiere el método)
var txt=txt.toLowerCase().replace('j','i')
var r=''
for(var a=0;a<txt.length;a++){
//Comprobamos si el carácter es un espacio
if(txt.charAt(a)!=' '){
//Buscamos la posición del carácter en el
abecedario
var l=txt.charAt(a)
l=let.indexOf(l)
//Comprobamos la posición de la fila y columna
var c1=Math.floor(l/let.length*tra.length)
var
c2=Math.round(((l/let.length*tra.length)*tra.length)-(c1*tra.length))
//Añadimos la letra correspondiente a la fila y
columna
r+=tra.charAt(c1)+tra.charAt(c2)
}else{
r+=' '
}
}
return r
}
//función de desencriptación
function polybios_dec(txt){
var pat=/^[ABCDE\s]*$/
if(!pat.test(txt)) return 'Texto no válido'
var t=txt,r='',c
while(t.length>0){
if(t.substr(0,1)==' '){
r+=' '
c=1
}
else{
var s=t.substr(0,2).split('')
r+=let.charAt((tra.indexOf(s[0])*tra.length)
+tra.indexOf(s[1]))
c=2
}
t=t.substr(c,t.length-c)
}
return r
}
Ambas funciones solo necesitan el argumento con el texto a encriptar o desencriptar.
El cifrador del César (siglo I a. C.)
Los romanos hace 2100 años idearon su propio sistema de enscriptación (a la altura de
los anteriores) que consistía en sustituir cada letra por otro que es el resultado de
desplazar tres posiciones hacia la derecha desde el carácter origen en el abecedario (con
la imagen de abajo se entenderá a la perfección).
Esta técnica se podría mejorar cambiando el abecedario “desplazado” por uno aleatorio,
por ejemplo, pero el método en principio es desplazando tres caracteres a la derecha (y
para desencriptarlo hacerlo al contrario, a la izquierda).
Nota: este sistema puede admitir también los espacios, que se añadirán como un carácter
más o de no usarse se omitirán.
Para poner otro ejemplo vamos a encriptar la siguiente cadena (contaremos los espacios):
Genbeta Dev Historia de la criptografia Metodo usado por los romanos
Y el resultado es el siguiente:
jhqehwdcghycklvwruldcghcodcfulswrjudildcphwrgrcxvdgrcsrucorvcurpdqrv
Y por último he hecho este otro ejemplo funcional del sistema de enscriptación del César,
que admite distinto número de desplazamiento (n), sea positivo o negativo (si lo
encriptamos con n=3 debemos de desencriptarlo con n=-3).
function cesar(txt,n,space){
//Comprobamos que el texto es válido
var pat=/^[0-9A-z\s]*$/
if(!pat.test(txt)) return 'Texto no válido'
//Adaptamos el texto según si admitimos espacios
var let='abcdefghijklmnopqrstuvwxyz'+(space?' ':'')
var txt=txt.toLowerCase()
if(!space) for(var a=0;a<txt.length;a++) txt=txt.replace(' ','')
//Ajustamos el desplazamiento de "n"
var n=n%let.length,r=''
n=n<0?let.length+n:n
for(var a=0;a<txt.length;a++){
//Desplazamos el abecedario
l=let.charAt((let.indexOf(txt.charAt(a))+n)%let.length)
r+=l.length==0?' ':l
}
return r
}
Esta función sirve para encriptar y desencriptar (debemos de restar el desplazamiento
simplemente) y necesita los siguientes argumentos: cesar([Texto],[Entero:
desplazamiento],[Booleano: con o sin espacios]).
El CheckSum
Cuando hablamos de CheckSum o Suma de Verificación nos estamos refiriendo a una función hash computable mediante un algoritmo cuyo propósito principal es detectar cambios en una secuencia de datos (archivos) para proteger la integridad de estos, comprobando así que no haya diferencias entre los valores obtenidos al hacer una comprobación inicial y otra final luego de haber compartido dichos datos; es decir, es usado para verificar que un archivo compartido a un usuario es idéntico bit a bit al publicado en su fuente original .
Imagina que queremos almacenar o compartir información con alguien, pero a la vez queremos protegernos frente a errores inesperados en el almacenamiento o transmisión de esta información, en aquellas situaciones resulta útil acompañar a los datos de sus respectivos valores hash obtenidos a partir de ellos aplicando funciones hash con ciertas propiedades de forma que puedan ser usados para verificar (hasta cierto punto) el propio dato compartido. Precisamenteal valor hash se le llama Suma de verificación o CheckSum.
El CheckSum es muy usado por empresas desarrolladoras de software ya que permite comprobar la integridad de los contenidos que ofrecen. Por ejemplo, cuando se distribuye un contenido por la red (una imagen ISO, IMG, un archivo RAR, un ejecutable EXE, etc), y se quiere estar seguro de que
lo que le llega al usuario/cliente es lo que se está emitiendo, se proporciona un valor hash del contenido de forma que ese valor tiene que obtenerse al aplicar la función hash sobre el contenido distribuido asegurando así la integridad. En este caso el CheckSum recibe el nombre de CheckSum Criptográfico debido a que es un checksum que requiere el uso de funciones hash criptográficas para que sea difícil generar otros ficheros falsos que tengan el mismo valor hash.
Otro ejemplo de uso de estos conceptos para verificar la integridad es calcular y guardar el valor hash de archivos para poder verificar posteriormente que nadie los ha modificado, y cuando hablamos de haberlo modificado me refiero a insertar código malicioso como malware, adware, troyanos o virus. Esto último es lo nos puede resultar más interesante ya que está involucrado directamente con lo que deseamos evitar, y es que nadie quiere descargar un fichero o archivo y que al final resulte no ser el archivo prometido sino un tipo de amenaza a nuestros equipos.
El Message-Digest Algorithm 5 o MD5
Message-Digest 5 (MD5) es un algoritmo criptográfico de 128 bits ampliamente difundido, el cual puede ser usado, entre otras cosas, para realizar la comprobación de la integridad de archivos como son binarios EXE, imágenes ISO o cualquier otro tipo de fichero descargados desde alguna fuente de Internet de manera que nos proporcione la seguridad de que el archivo descargado no se ha alterado o modificado por terceros.
Comparando una Suma MD5 publicada con la Suma de Comprobación del archivo descargado, un usuario puede tener la confianza suficiente de que el archivo es igual al publicado por los desarrolladores. Esto protege al usuario contra malware y virus en general ya que algún otro usuario malicioso podría incluir ese tipo de software modificando el archivo original.
Otro de los puntos importantes es que la comprobación de un archivo descargado contra su suma MD5 no detecta solamente los archivos alterados de una manera maliciosa, sino que también reconoce una descarga corrupta o incompleta como la descarga de una imagen ISO de un sistema operativo, así podremos comprobar que no tengan errores entre sus archivos antes de grabarlos
a un DVD o pasarlas a un USB.
Un ejemplo de cómo luciría la suma MD5 de un fichero sería:
Nombre: test.pngMD5: 4ef72b35fed1cd10ab6c8d2921bf4962
Muchos desarrolladores de distribuciones linux comparten sus imágenes ISO de instalación acompañado de su respectivo MD5 para que el usuario sea capaz de comprobar la integridad del archivo.
El Secure Hash Algorithm o SHA
El SHA o Secure Hash Algorithm es un sistema de funciones hash criptográficas que producen una salida resumen de 160 bits y que es ámpliamente usado como medida de seguridad pues, al igual que el MD5, nos permite comprobar la originalidad e integridad de de archivos descargados. Pero además es uno de los algoritmos más usados para guardar de manera encriptada datos muy sensibles como contraseñas, así como en el proceso de firmar digitalmente diferentes documentos (mayor información).
Como dato histórico, el primer miembro de la familia fue oficialmente llamado SHA, publicado en 1993. Sin embargo, hoy en día, no oficialmente se le llama SHA-0 para evitar confusiones con sus sucesores. Dos años más tarde el primer sucesor de SHA fue publicado con el nombre de SHA-1, que actualmente es uno de los más usados al distribuir software. También existen cuatro variantes más que se han publicado desde entonces con algunas otras diferencias: SHA-224, SHA-256, SHA-384, y SHA-512 (llamándose SHA-2 a todos ellos).
Un ejemplo de cómo luciría el hash SHA-1 de un fichero sería:
Nombre: test.pngSHA-1: 33d0f57fb6d7e43d4bbe2a3d6e1878dffd1a7aed
Microsoft es una de las empresas que más usan el hash SHA-1 para facilitar que los usuarios puedan comprobar la originalidad e integridad de sus productos distribuidos en imagenes ISO o ejecutables EXE. Por ejemplo la siguiente imágen que corresponde al reciente Windows 8.1 Preview:
Otro ejemplo es The Fedora Project, desarrolladores de una distribución linux del mismo nombre, quienes a su vez usan el hash SHA-256 para realizar las comprobaciones de sus imagenes ISO como pueden ver en el siguiente link. En nuestro ejemplo se muestra el SHA-256 de la versión 19 de Fedora de 64bit:
-----BEGIN PGP SIGNED MESSAGE-----Hash: SHA256
# The image checksum(s) are generated with sha256sum.6e7e263e607cfcadc90ea2ef5668aa3945d9eca596485a7a1f8a9f2478cc7084 *Fedora-19-x86_64-DVD.isoef9eb28b6343e57de292f2b2147b8e74a2a04050655e0dc959febd69b0d5d030 *Fedora-19-x86_64-netinst.iso
El Cyclic Redundancy Check 32 o CRC32
Se trata de un código de detección de errores usado frecuentemente en redes digitales y en dispositivos de almacenamiento cuyo propósito principal es comprobar o detectar cambios accidentales en los datos o alteración de los mismos.
Como se ha mencionado, es útil para detección de errores, pero, en condiciones de seguridad, no podemos confiar en que el CRC puede verificar plenamente que los datos son los correctos en caso de que se hayan producido cambios deliberados y no aleatorios.
A menudo se piensa que si, cuando llega un mensaje, éste y su CRC coinciden, quiere decir que el mensaje no ha podido ser alterado durante su transmisión. Esta suposición es falsa porque CRC es un mal método de cifrado de datos. De hecho, el CRC no se trata realmente de un método de cifrado, lo que realmente hace es utilizarse para el control de integridad de datos , pero en algunos casos se supone que se utilizarán para el cifrado.
Notemos que el CRC es un valor numérico que se calcula usando los datos originales de forma que este valor está fuertemente ligado precisamente a estos datos, por tanto si los datos cambian entonces el valor del CRC también cambia.
Un ejemplo de cómo luciría el CRC32 de un fichero sería:
Nombre: test.pngCRC-32: 9b8fcbd6
WinRAR, el popular programa compresor y descompresor de datos, usa el CRC32 para comprobar archivos. Cuando WinRAR descomprime un fichero vuelve a calcular su CRC y lo compara con el CRC de los datos originales almacenado en el archivo RAR. Si los valores calculados son diferentes entonces los datos también son diferentes y el fichero extraído no es idéntico al fichero original obteniéndose en esos casos un mensaje común como "Error de CRC" que significa que el archivo está dañado, o, si está protegido con contraseña, que la contraseña usada es incorrecta.
Y con todo esto, ¿Por qué sería necesario calcular el MD5, SHA-1, CRC32, etc?
Les daré un ejemplo en concreto. En el chat del blog muchas personas nos vienen preguntando luego de descargar la ISO de Windows 7 o Windows 8, comentándonos que por algún motivo no pudieron hacer que la instalación se llevara a cabo bajo ninguna posibilidad. Es allí cuando les decimos de primera "¿Verificaste el hash justo después de descargar? ¿cierto?", y la respuesta común que conseguimos es "No, ¿qué es eso?"
Es aquí donde viene la importancia de este post, pues considero absolútamente necesario que usted verifique la autenticidad de los archivos que ha descargado, sobre todo si son imagenes ISO de sistemas operativos que acaba de descargar. Si lo hace, confirmará que NO ha sido modificado por terceras personas, que está limpio de spyware y virus, y que está libre de corrupción o de cualquier error de transferencia (incompleto por errores en la descarga).
La comprobación del hash es el único medio seguro por el cual puedes comprobar que tu descarga es exactamente igual (bit a bit) al archivo proporcionado por su fuente original, pues el método de que "si el peso es el mismo, entonces es correcto" no es siempre suficiente.
¿Y que pasaría si al intentar comprobar el hash no coincide?
Hay dos posibilidades: (1) El archivo que haz descargado funcionará pero no como debería (esto dependerá de qué tan importante es aquella parte corrupta) o (2) El archivo simplemente no abrirá, no se ejecutará, o no se podrá grabar; es decir, es inservible.
En ambos casos la sugerencia general es volver a conseguir el archivo de su fuente original, es decir, volver a descargarlo.
¿Y en qué está relacionado todos estos conceptos con nuestro blog Conocimiento Adictivo?
Nuestro blog ya lleva muchos meses usando la comprobación de ficheros por su suma MD5 en los posts de descargas, esto con el único fin de que nuestros visitantes puedan verificar la originalidad e integridad de los archivos que compartimos así como verificar su descarga completa.
Noten además que para facilitarles aún más la tarea de comprobación hemos implementado que el nombre de los archivos correspondan a su MD5 Sum para que tengan de esta forma a mano siempre el MD5 Sum de los archivos que son descargados desde nuestro blog.
Por ejemplo veamos el caso del aporte de descarga "PowerISO 5.7", si se dirigen al post de este artículo, verán la siguiente información en la sección "Enlaces de Descarga":
PROGRAMA
Multilenguaje | RAR | 5.84 MB
Contenido: PowerISO.v5.7.Final
MD5 Checksum: 676fd77af0c161c30f169f6c115f0226
Como pueden notar nosotros ya venimos proporcionándoles el MD5 Checksum, el mismo que será el propio nombre de descarga del archivo que podrá ser visualizado al momento de descargar los archivos RAR, y no sólo eso, sino que ese MD5 Checksum será su ID único con el cual podrán verificar la originalidad de nuestros archivos asi como su integridad luego de la descarga.
Esta implementación es con la finalidad de brindarles un mejor soporte y por su propia seguridad. No es una obligación pero si muy recomendable.
Herramienta que puedes usar para calcular el hash SHA-1, MD5 y CRC32 de los archivos que descargues
Para obtener este tipo de datos existen muchas aplicaciones; sin embargo, la que veremos en esta ocasión esHashcheck, una pequeñísima aplicación que cumple muy bien su objetivo a la hora de conocer estos datos para cualquier tipo de archivos.
HashCheck Shell Extension hace que sea fácil y rápido para cualquiera el poder calcular y verificar sumas de comprobación (CheckSums) y hashes desde el propio Explorador de Windows, para ello integra la funcionalidad de la suma de comprobación de archivos en la opción de Propiedades de cualquier archivo. Además HashCheck es capaz de crear y verificar archivos SFV y otros tipos de archivos de control, como los archivos .Md5
Descargacode.kliu.org/hashcheck/
Tipos de criptografía: simétrica, asimétrica e hibrida
Criptografía simétrica
La criptografía simétrica solo utiliza una clave para cifrar y descifrar el mensaje, que tiene
que conocer el emisor y el receptor previamente y este es el punto débil del sistema, la
comunicación de las claves entre ambos sujetos, ya que resulta más fácil interceptar una
clave que se ha transmitido sin seguridad (diciéndola en alto, mandándola por correo
electrónico u ordinario o haciendo una llamada telefónica).
Teóricamente debería de ser más fácil conocer la clave interceptándola que probándola
una por una por fuerza bruta, teniendo en cuenta que la seguridad de un mensaje cifrado
debe recaer sobre la clave y nunca sobre el algoritmo (por lo que sería una tarea eterna
reventar la clave, como comenté en un ejemplo de ataque por fuerza bruta).
Para poner un ejemplo la máquina Enigma (que era una maquina de cifrado
electromecánica que generaba abecedarios según la posición de unos rodillos que
podrían tener distintas ordenes y posiciones) usaba un método simétrico con un algoritmo
que dependía de una clave (que más que clave parece un ritual) que está formada por:
los rotores o rodillos que usaba, su orden y la posición de cada anillo, siendo esto lo más
básico.
La máquina Enigma contaba también con un libro de claves que contenía la clave del
día y hacia un poco más difícil encontrar la clave, pero no es una clave lo suficientemente
segura como para que no se pudiese reventar, sobretodo cuando los ingleses gracias a
los polacos consiguieron el algoritmo, por este motivo la mayoría de los días conseguían
la clave.
Y otro inconveniente que tiene este sistema es que si quieres tener un contenido
totalmente confidencial con 10 personas tienes que aprenderte o apuntarte (siendo esta
forma menos segura) las 10 claves para cada persona.
Criptografía asimétrica
La criptografía asimétrica se basa en el uso de dos claves: la pública (que se podrá
difundir sin ningún problema a todas las personas que necesiten mandarte algo cifrado)
y la privada (que no debe de ser revelada nunca).
Sabiendo lo anterior, si queremos que tres compañeros de trabajo nos manden un archivo
cifrado debemos de mandarle nuestra clave pública (que está vinculada a la privada) y
nos podrán mandar de forma confidencial ese archivo que solo nosotros podremos
descifrar con la clave privada.
Puede parecer a simple vista un sistema un poco cojo ya que podríamos pensar que
sabiendo la clave pública podríamos deducir la privada, pero este tipo de sistemas
criptográficos usa algoritmos bastante complejos que generan a partir de la frase de paso
(la contraseña) la clave privada y pública que pueden tener perfectamente un tamaño de
2048bits (probablemente imposible de reventar).
Como os habréis dado cuenta solo cifra una persona (con la clave pública) y la otra se
limita a mirar el contenido, por lo que la forma correcta de tener una comunicación
bidireccional sería realizando este mismo proceso con dos pares de claves, o una por
cada comunicador.
Otro propósito de este sistema es también el de poder firmar documentos, certificando
que el emisor es quien dice ser, firmando con la clave privada y verificando la identidad
con la pública.
Nota: todo esto puede parecer lioso (y lo es) pero hablaré de como poner en práctica esto
conGnuPG (una herramienta de cifrado libre muy usada para este propósito) y será más
fácil de comprender.
Diferencias entre criptografía simétrica y asimétrica
Para empezar, la criptografía simétrica es más insegura ya que el hecho de pasar la clave
es una gran vulnerabilidad, pero se puede cifrar y descifrar en menor tiempo del que tarda
la criptografía asimétrica, que es el principal inconveniente y es la razón por la que existe
la criptografía híbrida.
Criptografía híbrida
Este sistema es la unión de las ventajas de los dos anteriores, debemos de partir que el
problema de ambos sistemas criptográficos es que el simétrico es inseguro y el asimétrico
es lento.
El proceso para usar un sistema criptográfico híbrido es el siguiente (para enviar un
archivo):
Generar una clave pública y otra privada (en el receptor).
Cifrar un archivo de forma síncrona.
El receptor nos envía su clave pública.
Ciframos la clave que hemos usado para encriptar el archivo con la clave pública del
receptor.
Enviamos el archivo cifrado (síncronamente) y la clave del archivo cifrada
(asíncronamente y solo puede ver el receptor).
Manual de GPG: cifra, firma y envía datos de forma segura
Hemos hablado ya sobre la criptografía simétrica y asimétrica y sobre la firma digital, solo
toca ponerlo en práctica con GnuPG (la versión libre de PGP o mejor dicho Pretty Good
Privacy), con el que cifraremos cualquier tipo de archivo que podremos mandar
“libremente” con cierta seguridad de que nadie lo podrá leer. Y puede que a muchos os
ayude a entender como funciona la criptografía y como funciona el polémico cifrado
de Mega, que tanto está dando que hablar estos días.
¿Qué es GnuPG?
Antes de empezar con lo interesante tenemos que saber que es GPG (GNU Privacy
Guard), que es un derivado libre de PGP y su utilidad es la de cifrar y firmar digitalmente,
siendo además multiplataforma (podéis descargarlo desde la página oficial) aunque viene
incorporado en algunos sistemas Linux, como en Ubuntu (será con el sistema que haré
todos los ejemplos, en Windows se encuentra solo con gestor gráfico).
Anillo de claves
GPG tiene un repositorio de claves (anillo de claves) donde guarda todas las que tenemos
almacenadas en nuestro sistema, ya sean privadas o públicas (como comenté, con la
clave pública cifraremos un mensaje que solo podrá descifrar el que posee la clave
privada).
Más adelante cuando veamos un anillo de claves debemos de recordar que pub hace
referencia a la clave pública y sub hace referencia a la privada (y que tenemos que tener
a buen recaudo).
Servidores de claves
Para que nos cifren un mensaje tenemos que compartir la clave pública de nuestro par de
claves para cifrar, y como es un poco engorroso difundir una clave a muchas personas
existen los servidores de claves PGP (compatibles con GPG), donde subiré una clave
pública para el que quiera probar los ejemplos.
Unos ejemplos de servidores son estos: pgp.rediris.es (español, aunque falla
algunas veces) opgp.mit.edu (americano, del MIT y a mi no me ha dado problemas).
Cifrado simétrico
Como ya sabéis el cifrado simétrico es el tipo de cifrado más sencillo que hay, es más rápido de procesar y por desgracia menos seguro que el cifrado asimétrico.
Para empezar la prueba tenemos que tener un archivo de cualquier tipo e introducir en la
terminal de Linux el comando gpg con el parámetro -c para cifrar y -d para descifrar.
pedro@ubuntu:~/gpg$ echo "Genbeta Dev" > texto.txt
pedro@ubuntu:~/gpg$ gpg -c texto.txt
Tras crear un archivo de texto usamos el comando gpg -c [archivo], nos aparecerá
un cuadro que nos pide la contraseña y se generará un archivo .gpg. Y después lo
descifraremos con el comando gpg -d [archivo] (e introduciendo la clave de alta
seguridad, en este caso qwerty).
pedro@ubuntu:~/gpg$ gpg -d texto.txt.gpg
gpg: datos cifrados CAST5
gpg: cifrado con 1 frase contraseña
Genbeta Dev
gpg: AVISO: la integridad del mensaje no está protegida
Podéis probar a descifrar este archivo usando la clave qwerty.
Cifrado asimétrico
Generar las claves
Para poder cifrar asimétricamente primero tenemos que crear la pareja de claves (pública
y privada) con el comando gpg --gen-key.
pedro@ubuntu:~/gpg$ gpg --gen-key
gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Por favor seleccione tipo de clave deseado:
(1) RSA y RSA (predeterminado)
(2) DSA y Elgamal
(3) DSA (sólo firmar)
(4) RSA (sólo firmar)
¿Su selección?:
GPG nos permite elegir el tipo de clave que queremos usar, hay opciones que solo
permiten firmar y otras que permiten firmar y cifrar, en este caso usaremos DSA y
Elgamal.
las claves DSA pueden tener entre 1024 y 3072 bits de longitud.
¿De qué tamaño quiere la clave? (2048)
Nos piden el tamaño de la clave que puede variar entre 1024 bits y 3072, esto es de libre
elección, yo tomaré el término medio que es el que propone por defecto (2048).
A partir de aquí todo es más trivial, nos pide la fecha en la que expirará la clave, la
información del emisor de la clave (nombre, mail y algunos datos extra que queramos dar)
y por último nos pedirá la contraseña que salvaguarda la clave privada.
Tras generar las claves podemos verlas con el comando gpg -k que nos muestra
nuestro anillo de claves, lo importante de este paso es que veremos la identificación de
cada una, que es necesaria para poderlas exportar y enviar.
pedro@ubuntu:~/gpg$ gpg -k
/home/pedro/.gnupg/pubring.gpg
------------------------------
pub 2048D/18384645 2013-01-23
uid Pedro Gutiérrez (Manual GPG - Genbeta Dev)
sub 2048g/C4A9EA7A 2013-01-23
Exportar y enviar la clave privada
El objetivo de esta pareja de claves es que cualquiera nos pueda mandar un archivo
cifrado que solo veremos nosotros y esto se hace difundiendo la clave pública que
acabamos de crear (la pública,nunca la privada), para exportarla en un archivo usaremos
el comando gpg -output [archivo destino] --export [ID de a clave
pública] (la clave pública generada antes tiene la ID18384645).
pedro@ubuntu:~/gpg$ gpg --output CPub.gpg --export 18384645
pedro@ubuntu:~/gpg$ ls
CPub.gpg
Este archivo ahora se puede difundir por el medio que queramos, tenemos que tener en
cuenta que el único problema de seguridad que habría en difundir la clave es que alguien
se hiciese pasar por otro al mandarnos un mensaje, algo que pasaría igual si no estuviese
cifrado, por eso el que nos envíe algo lo debería de firmar (si fuese pertinente).
Podéis descargar esta clave pública, que ahora veremos como importar y sirve para
mandarme un archivo cifrado o para comprobar que un archivo lo he firmado yo.
Subir una clave pública a un servidor de claves
Los servidores de claves suelen ser de acceso público (al no haber mucho problema por
difundir una clave pública) y en este caso subiremos una clave a los servidores
del MIT (pgp.mit.edu) usando el comando gpg --send-keys --keyserver
[Dirección del servidor] [ID de la clave pública] (al igual que antes la
ID es 18384645).
pedro@ubuntu:~/gpg$ gpg --send-keys --keyserver pgp.mit.edu 18384645
gpg: enviando clave 18384645 a hkp servidor pgp.mit.edu
A partir de este momento la clave estará accesible desde este servidor específico.
Importar la clave desde el archivo o servidor de claves
Para poder usar la clave pública para cifrar o comprobar la identidad del remitente
tenemos que importar previamente la clave, desde un archivo debemos de usar el
comando gpg --import [Archivo de la clave pública] (el que hemos
descargado anteriormente).
pedro@ubuntu:~/gpg$ gpg --import CPub.gpg
gpg: clave 18384645: «Pedro Gutiérrez (Manual GPG - Genbeta Dev)
<[email protected]>» sin cambios
gpg: Cantidad total procesada: 1
gpg: sin cambios: 1
Al tener la clave ya en mi anillo de claves me contesta que no hay cambios.
Para realizar la importación desde el servidor tenemos que usar el comando gpg --
keyserver [Dirección del servidor] --recv-keys [ID de la clave].
pedro@ubuntu:~/gpg$ gpg --keyserver pgp.mit.edu --recv-keys 18384645
gpg: solicitando clave 18384645 de hkp servidor pgp.mit.edu
gpg: clave 18384645: «Pedro Gutiérrez (Manual GPG - Genbeta Dev)
<[email protected]>» sin cambios
gpg: Cantidad total procesada: 1
gpg: sin cambios: 1
Como podemos ver al tener ya la clave nos devuelve el mismo mensaje.
Cifrar con la clave pública
Ahora tenemos que pensar que hemos importado una clave pública, por ejemplo de
nuestro jefe y tenemos que mandarle un documento, para cifrar el documento usaremos
el comando gpg —encrypt —recipient [ID de la clave] [Archivo]
pedro@ubuntu:~/gpg$ echo "Genbeta Dev" > documento.txt
pedro@ubuntu:~/gpg$ gpg --encrypt --recipient 18384645 documento.txt
pedro@ubuntu:~/gpg$ ls
documento.txt documento.txt.gpg
Y ya tenemos el archivo listo para mandarlo de forma segura.
Descifrar un archivo con la clave privada
Y ahora es el momento de descifrar con nuestra clave privada el documento tras recibirlo,
con el comando gpg -d [Archivo] e introduciendo la contraseña que creamos para
salvaguardar la clave privada.
pedro@ubuntu:~/gpg$ gpg -d documento.txt.gpg
Necesita una frase contraseña para desbloquear la clave secreta
del usuario: "Pedro Gutiérrez (Manual GPG - Genbeta Dev)
clave ELG-E de 2048 bits, ID C4A9EA7A, creada el 2013-01-23 (ID de clave
primaria 18384645)
gpg: cifrado con clave ELG-E de 2048 bits, ID C4A9EA7A, creada el 2013-
01-23
«Pedro Gutiérrez (Manual GPG - Genbeta Dev) <[email protected]>»
Genbeta Dev
Y el resultado nos lo muestra a continuación (Genbeta Dev), aunque si queremos
especificar la salida debemos de usar el parámetro -o [Archivo de salida].
Firmar archivos
Una de las medidas de seguridad básicas al pasar un mensaje es asegurarnos que el
emisor es quien dice ser, para asegurarnos de esto digitalmente existe la firma digital, en
el artículo anteriorexpliqué como GPG usaba los hash para crear una firma simple, pero
también podemos cifrarlo y a su vez firmarlo, que es lo que haremos con el comando gpg
-u [ID de la clave privada] --output [Archivo resultante] --sign
[Archivo para firmar] e introduciendo la contraseña de la clave privada.
pedro@ubuntu:~/gpg$ echo "Genbeta Dev" > firmar.txt
pedro@ubuntu:~/gpg$ gpg -u C4A9EA7A --output firmar.txt.gpg --sign
firmar.txt
Necesita una frase contraseña para desbloquear la clave secreta
del usuario: "Pedro Gutiérrez (Manual GPG - Genbeta Dev)
clave DSA de 2048 bits, ID 18384645, creada el 2013-01-23
Y ahora para asegurarse la confidencialidad del documento (ahora que esta firmado por
nosotros) deberíamos de cifrarlo con la clave pública del destinatario.
Verificar y descifrar un archivo firmado
Cualquiera con la clave pública asociada a la que ha firmado el documento puede leerlo,
de la misma forma que desciframos un archivo (gpg -d [Archivo]) o verificándolo
únicamente con el comandogpg --verify [Archivo].
pedro@ubuntu:~/gpg$ gpg --verify firmar.txt.gpg
gpg: Firmado el mié 23 ene 2013 05:25:18 CET usando clave DSA ID 18384645
gpg: Firma correcta de «Pedro Gutiérrez (Manual GPG - Genbeta Dev)
Y el resultado es la información del remitente, que podéis comprobar vosotros con este
archivo y con la clave pública de los pasos anteriores.
Resumen
GPG es una herramienta de cifrado muy potente y fácil de usar, que en principio, a la
mayoría no nos hace falta, pero puede que se nos presente la necesidad de enviar algo
por medio inseguros (porque no haya más remedio), haciéndolo de esta forma podremos
hacerlo sin miedo ha que lean el contenido del archivo o nos den el cambiazo.
Este es un tema bastante extenso y si no lo acabas de entender puede ser un lío, pero
para preguntar están los comentarios.
http://www.genbetadev.com/