Funciones hash
Introducción
La tecnología se ha desarrollado tan rápidamente en la mayoría de las áreas de informática que es fácil pasar por alto las áreas que no se han desarrollado en las últimas décadas. La autenticación basada en contraseña es probablemente una de las funciones técnicas más importantes que todos usamos todos los días, sin embargo, no ha evolucionado mucho desde los primeros sistemas informáticos de usuarios múltiples.
El término autenticación (o autentificación) se refiere al servicio que trata de asegurar que una comunicación sea auténtica, es decir, verificar que el origen de los datos es el correcto, quién los envió y cuándo fueron enviados y recibidos también sean correctos.
Anteriormente se había tratado el tema de la autenticación con el uso de Kerberos, esta vez el método a abordar son las funciones hash.
Hash
Una función Hash es un algoritmo matemático que, con una entrada A, nos da una salida B. Son también llamadas funciones de resumen y se emplean en el área de la criptografía para asegurar la autenticidad de un documento (como firma digital), para proteger contraseñas o para asegurar la integridad de la información.
Puede ser cualquier algoritmo matemático pero tiene que cumplir una serie de propiedades:
- Para una misma función hash, sea cual sea la longitud de la entrada A la salida B tiene que ser de un tamaño fijo
- Para cada A, B tiene que ser única.
- Tiene que ser rápido y fácil de calcular.
- No se puede volver a A desde B.
- No puede presentar colisiones. Esto quiere decir que para dos A diferentes no se puede dar un mismo B. Esto como tal es imposible, pero es muy importante que las colisiones sean mínimas y que encontrarlas sea muy difícil.
- Se requiere de forma adicional que sean uniformes (para una A elegida aleatoriamente todos los valores hash son equiprobables) y con efecto avalancha (un cambio de un único bit en A supone una B completamente diferente).
SHA-1 (Secure Hash Algorithm)
Este algoritmo fue desarrollado por el NIST y publicado como estándar federal para el procesamiento de la información; en 1995 se publicó una versión revisada conocida como SHA-1.
El algoritmo toma como entrada mensajes de longitud máxima de 264 bits que son procesados en bloques de 512 bits; el resultado que produce es de 160 bits.
Proceso:
- Se incorporan bits de relleno al mensaje de entrada de tal modo que cumpla: longitud=448mod512. El relleno consiste en un uno seguido de los ceros que sean necesarios. Aunque el mensaje ya tenga la longitud deseada, se debe efectuar el relleno, por lo que el número de bits de dicho relleno está en el rango de 1 a 512 bits.
- Se le añade un bloque de 64 bits que represente la longitud del mensaje original antes de ser rellenado.
- Se inicializa la memoria temporal MD, la cual consta de 160 bits y su finalidad es almacenar los resultados intermedios y finales de la función de dispersión. La MD consta de 5 registros (A,B,C,D,E) de 32 bits cada uno, los valores con los que se inicializan son los siguientes (valores hexadecimales):
- 67452301
- EFCDAB89
- 98BADCFE
- 10325476
- C3D2E1F0
- Se procesa el mensaje por bloques de 512 bits, cada uno pasa por un módulo que consta de 4 rondas de procesamiento de 20 pasos cada una. Las rondas tienen una estructura similar, con la excepción de que cada una ocupa una función lógica primitiva diferente (f1, f2, f3 y f4).
- La entrada a cada ronda consta del bloque de 512 bits que se esté procesando (Yq) y los 160 bits de la memoria MD, cada bloque de 512 bits actualizará el valor de la memoria temporal. Cada ronda también hace uso de la constante aditiva Kt, donde t indica uno de los 80 pasos a lo largo de las cuatro rondas.
- Una vez que se procesan los L bloques de 512 bits, el resumen del mensaje son los 160 bits de salida del último bloque.
Esquema:
MD5
El algoritmo MD5 fue desarrollado por Ron Rivest en 1992 en el MIT con la finalidad de robustecer el MD4 y a la fecha se trata del algoritmo hash más seguro y de mayor uso en el mundo.
MD5 procesa mensajes de cualquier longitud y procesa bloques uniformes de 512 bits a la vez, hasta concluir con el mensaje total a fin de entregar a la salida un bloque "resumen" de 128 bits.
Proceso:
- En principio, para que el mensaje sea procesado en bloques de tamaño fijo se requiere que su longitud en bits sea: longitud=448mod512, de manera que su longitud sea de no menos de 64 bits de diferencia para completar un múltiplo de 512, así, de ser necesario se aplica un relleno, el cual varía en longitud en cada caso, esto es, el número de bits adicionados está en un rango de 1 a 512 bits con el formato 10000…0.
- Una representación de 64 bits de la longitud del mensaje original (antes de aplicar el relleno) se añade al resultado del paso 1.
- Da inicio el proceso de reducción, para ello se utiliza un registro de 128 bits que permite almacenar y mantener los resultados intermedios y final de la función hash. El registro se divide en cuatro secciones de 32 bits cada una, las cuales corresponden a las variables A, B, C, y D que son inicializadas con los valores hexadecimales:
- 67452301
- EFCDAB89
- 98BADCFE
- 10325476
Estas variables son llamadas variables de concatenación o variables de encadenamiento y se almacenan en formato little-endian de manera que aparecen:
- 01 23 45 67
- 89 AB CD EF
- FE DC BA 98
- 76 54 32 10
- El mensaje se procesa en bloques de 512 bits a la vez a través de 16 bloques de 32 bits cada uno, para lo cual las cuatro variables de concatenación se copian en variables distintas: a = A, b = B, c = C, d = D.
La parte medular del algoritmo es una función de compresión que consta de cuatro rondas, las cuales tienen una estructura similar; pero cada una utiliza operaciones distintas durante 16 iteraciones; cada operación realiza una función no lineal sobre tres de las variables a, b, c y d, y el resultado es sumado a la cuarta variable que no fue elegida, un sub-bloque del texto y una constante.
A ese resultado se le aplica una rotación circular a la izquierda un número variable de bits y se suma el resultado a una de las variables a, b, c o d. Finalmente el resultado reemplaza a una de las variables a, b, c o d. La salida de la cuarta ronda se suma a la entrada de la primera en una operación modular 232.
Hay cuatro operaciones no lineales utilizadas, una para cada ronda:
Estas funciones son designadas de forma que si los bits que corresponden a, b, c y d son independientes y no perjudiciales, cada bit del resultado también será independiente y no perjudicial. La función F es una función condicional: If b then c else d, de manera similar G: If d then b else c, en tanto la función H genera un bit de paridad.
- Al final de todos los ciclos, a, b, c y d son sumados a A, B, C y D respectivamente y el algoritmo continúa con el siguiente bloque de datos. Y después de que todos los bloques de 512 bits (cada uno) han sido procesados se obtiene la salida final, esto es, la concatenación de A, B, C y D que produce un bloque de 128 bits.
Conclusiones
Las funciones hash tienen varias ventajas además de la facilidad de implementación, son versátiles y muy útiles para cualquiera de sus posibles aplicaciones, por estas razones son altamente utilizadas para proporcionar servicios de seguridad. A pesar de que fueron creadas hace más de dos décadas, su uso sigue vigente y muy probablemente seguirá así, ya que son confiables y díficiles de vulnerar.
Referencias
Facultad de Ingeniería. (2012). Fundamentos de Criptografía. Noviembre 19, 2017, de UNAM Sitio web: http://redyseguridad.fi-p.unam.mx/proyectos/criptografia/criptografia/
Corrales, H., Cilleruelo, C. & Cuevas, A. (2014). Criptografía y Métodos de Cifrado. Noviembre 19, 2017, de Universidad de Alcalá Sitio web: http://www3.uah.es/libretics/concurso2014/files2014/Trabajos/Criptografia%20y%20Metodos%20de%20Cifrado.pdf
Stallings, W. (2004). Fundamentos de Seguridad en Redes, Aplicaciones y Estándares. España: PEARSON EDUCACIÓN, S.A.