Funciones Hash
Tags: hash, spanish, j4fun, linux
Published: 2020-03-06 00:32:11

Estoy de vuelta con un nuevo tema que he estado investigando por mi cuenta y quería compartir con vosotros lo que he aprendido, he de mencionar que no soy ningún experto en la materia, asi que si hay algún error que corregir o mejora que añadir, vuestros comentarios serán bienvenidos.

¿Qué es una función hash?

Una función o también conocida como función resumen, es una relación entre 2 conjuntos mediante la cual dado un determinado dato de entrada perteneciente al primer conjunto, a este le corresponderá un valor perteneciente al segundo conjunto. Esta transformación de un valor a otro se hace mediente algun algortimo.

Una función hash pretende ser (matemáticamente hablando) una función biyectiva, es decir, si todos los datos/elementos/valores del conjunto de inicio tiene una imagen distinta del conjunto de llegada, y a cada elemento/dato/valor del conjunto de llegada le corresponde un único valor/elemento/dato del conjunto de llegada. Veamos esto en una imagen para que quede más claro:


![Funcion](https://i.ibb.co/hChR2nT/Screenshot-20200228-171712.png)

Las funciones hash están diseñadas de modo que sea cual sea la cantidad de información de entrada, a la hora de la salida esta siempre tenga una determinada longitud, por ejemplo, si queremos calcular el hash de un archivo de texto plano cuyo peso sea de 1033 Bytes, este nos dará como resultado una cadena de caracteres de longitud 10. Pues bien ahora queremos calcular la función resumen de un archivo ISO cuyo peso es de 4GB, pues bien quizá tarde algo más en sacarnos la función resumen pero al final como resultado nos dara otra cadena de caracteres de longitud 10.

Otro dato a tener en cuenta es que las en las funciones hash se busca que a la mínima que varíen los datos de entrada, el resultado final sea completamente distinto (esto se hace para evitar colisiones, que explicaré lo que es más adelante).

Veamos un ejemplo práctico:

Vamos a crear una par de archivos de texto con un contenido igual para ambos y después vamos a modificar alguno para ver qué es lo que pasa:

Vamos a usar el algortirmo MD5 para calcular los hash.

Usuarios de GNU/Linux:

Si eres usuario de GNU/Linux vamos a utilizar el comando **md5sum** su sintaxis es la siguiente: 

<code>md5sum [OPTION]... [FILE]...<code>

En nuestro caso no vamos usar las opciones, si no que directamente vamos a usar la ruta de nuestros archivos.

![cap1](https://i.ibb.co/GnTTmKK/abc.png)

Como se puede ver, tenemos en el escritorio 2 archvios llamados test1 y test2 cuyo contenido en el mismo, la frase: Hola mundo.

Vamos a utilizar el comando <code>md5sum</code> para calcular sus funciones resumen:

![cap2](https://i.ibb.co/HHs978Q/abc1.png)

Como se puede ver en la imagen de arriba tenemos como resultado de la función suma exactamente el mismo, puesto que el contenido de ambos archivos es el mismo, la frase "Hola mundo.".

Pues bien, ahora vamos a ver qué pasa si variamos un mínimo en contenido de uno de los archivos.

![cap3](https://i.ibb.co/Q6NQZ8p/abc2.png )

Como se puede apreciar hemos cambiado el contenido del segundo archivo, simplemente cambiando la letra 'm' minúscula a 'M' mayúscula y como se esperaba el resultado de la función hash es totalmente distinto ahora.

Al más mínimo cambio en los datos de entrada, el resultado cambia totalmente.



Vamos ahora cómo haríamos esto en un sistema con Windows 10:

Para el ejemplo tendremos 2 archivos de texto en el escritorio: test1.txt y test2.txt. Vamos a calcular la función resumen de ambos.

Para ello abriremos Windows PowerShell y usaremos el siguiente comando:


<code>Get-FileHash nombreDeArchivo -Algorithm MD5 |Format-List<code>

Y nos da el siguiente resultado:

![cap4](https://i.ibb.co/dkFDg8R/Captura.png)

Como podemos obserbar nos da el mismo resultado para ambos, esto quiere decir que tienen el mismo contenido.

Colisiones:

Voy a intentar explicar qué son. Como dijimos al principio intentamos que las funciones hash sean biyectivas, vagamente resumido esto quiere decir que a datos de entrada distintos, les corresponderán datos de salida totalmente diferentes.

Pero a veces ocurre que a datos de entradas diferentes la función nos devuelve valores iguales, esto es a lo que se le conoce como colisión.

Vamos un ejemplo (inventado) de esto:


![cap5](https://i.ibb.co/Df5kPQ7/abc3.png)

Como vemos tenemos un mismo valor de Hash con datos de entrada distintos, esto es un problema que en teoría no debería ocurrir, pues pueden darse difentes problemas, por ejemplo imaginemos que tenemos una aplicación de login que valida un usuario y un contraseña para acceder a un determinado servicio. Imaginemos que la contraseña se almacena no como texto plano (que es un problema de seguridad) sino que se almacenan como su función resumen, esto quiere decir que si nuestra contraseña es 'Zorro', también valdría 'Águila' como contraseña para acceder a nuestro sistema.

Pero si conseguimos el Hash de la password (pero no la password en sí) ¿Nos vadría para el login? La respuesta a priori es no, ya que ese Hash obtenido generaría otro Hash no coincidente con la base de datos, creo que este GiF lo explica muy bien:

![GIF](https://dev-to-uploads.s3.amazonaws.com/i/gfckwwv7cs3c47304alo.gif)

Bueno esto es todo por ahora.