Las funciones hash como alternativa al cifrado para garantizar la autenticidad de los mensajes
Introducción
La técnica más sencilla de utilizar para
garantizar la autenticidad de un texto que será enviado a través de una red es
simplemente cifrarlo con una clave secreta, compartida únicamente por emisor y
receptor. Con ello, se garantiza que el emisor es genuino, pues el receptor
sólo puede descifrar el mensaje con la clave compartida con ese único emisor. Un
oponente no puede enviar un mensaje, pues no tiene clave con la cual cifrarlo.
Una técnica un poco más avanzada es la de no cifrar
el mensaje original, y, en cambio, sólo enviar un pequeño bloque de bits al
final de los textos como referencia de autentificación. Sin embargo, así no se
proporciona la confidencialidad, y cualquier oponente podrá leer los mensajes.
Por ello, este enfoque se usa sólo en ciertas circunstancias, como cuando un
mensaje tiene receptores múltiples, o un receptor es tan lento que gastaría
muchos recursos al estar descifrando mensajes.
Aunque como tal no es un cifrado, pues no es
reversible (haciéndolo más seguro), existe una técnica que utiliza una clave
secreta, compartida por ambas partes, para crear un Código de Autentificación
de Mensajes (MAC), el cual se calcula con dicha clave y el mensaje, y se añade
al mismo. El receptor hace el mismo proceso, y con ello descubre dos cosas
básicas: que el emisor es el indicado y que el mensaje no se ha alterado.
Puede obtenerse únicamente un resumen del
mensaje, el cual será enviado anexo al mismo mensaje -tal como el MAC-, utilizando
la técnica del cifrado; por dos métodos: uno con cifrado simétrico y otro con
asimétrico. Con este último, se cumple la función de una firma digital: el mensaje
sólo puede ser descifrado con la clave pública del emisor, quien ha cifrado el
texto con su clave privada.
Sin embargo, se han buscado técnicas que eviten
no sólo cifrar el texto, sino tampoco cifrar siquiera el resumen del mismo. Existe
una técnica más sencilla pero más avanzada, pues implica un costo de hardware
menor, un software más rápido, y un menor uso de algoritmos de cifrado,
evitando cierto tipo de problemas: el uso de funciones hash, las cuales son el
objeto de este escrito.
Desarrollo
Una función hash recibe un mensaje, de tamaño
variable, y produce un resumen del mensaje, de tamaño fijo, el cual es enviado
junto con el mensaje. Las funciones hash, en lugar de usar claves secretas,
como un cifrado, utilizan un valor secreto común S. Un emisor concatena dicho
valor con el mensaje, calcula la función hash determinada con esos valores, y
envía dicho texto con el mensaje original. El receptor hace lo mismo, y con
ello, al igual que con MAC, verifica que el mensaje no se ha alterado y que el
emisor es el indicado.
Existen al menos seis características de una
función hash. Las primeras tres determinan su facilidad de uso e implementación:
pueden aplicarse a un bloque de datos de cualquier tamaño, producen una salida
de tamaño fijo, y son relativamente fáciles de calcular, haciendo que tanto las
implementaciones de hardware como de software sean prácticas.
Otras dos características son que es imposible
encontrar el valor secreto dado el resumen del mensaje (propiedad unidireccional),
y que es imposible encontrar un mensaje alternativo con el mismo valor hash
que un mensaje dado. Si una
función tiene los cinco atributos anteriores, se clasifica como función débil,
mientras que tener la siguiente la clasifica como robusta: que es imposible que
dos mensajes diferentes den resúmenes hash iguales.
Existen varias funciones hash, como las simples,
SHA-1, MD5, RIPEMD-160, y HMAC. En todas ellas, el mensaje original es una
secuencia de bloques de n bits, el cual es procesado bloque a bloque de forma
iterativa para producir una función hash de n bits. A continuación, se
describirá cada una de ellas.
En las funciones hash simples, todo el bloque
de entrada se separa en varios bloques de longitudes iguales, y se obtiene un
bit final de todos ellos, los cuales, al concatenarse, constituirán el código
hash final. El bit final de cada bloque se calcula realizando un XOR entre
todos los bits de ese bloque: ((1 XOR 2) XOR 3) XOR n.
La probabilidad de que un error en los datos
resulte en un valor hash inalterable es 2-n, donde n es el número de
bits; sin embargo, con datos más predecibles la función es menos efectiva (como
cuando siempre el primer bit de un byte es 0, reduciendo su efectividad de 2-128
a 2-112.)
Para mejorar la seguridad del proceso anterior,
se puede rotar un bit a la izquierda cada vez que se agregue un bit al valor
hash final. Sin embargo, si el texto original es claro, este último paso no es significativo,
pues sería relativamente fácil producir un mensaje diferente que produzca ese mismo
código hash: le basta al atacante con crear el mensaje deseado y añadir un
bloque de n bits que haga que el mensaje nuevo y el bloque produzcan el código
hash deseado.
Una técnica más avanzada, propuesta por la NSA
(National Standard Agency), consistía en realizar un XOR consecutivo de cada
bloque de bits, en lugar de por cada bit de cada bloque, obteniéndose el código
hash final. Por último, se realizaba un CBC con cada bloque del texto original
y el código hash final, obteniéndose varios bloques.
En 1993, el NIST (National
Institute of Standards and Technology) propuso un método mejor, el SHA-1, el
cual toma un mensaje con una longitud máxima menor que 264 bits, la procesa
en bloques de 512 bits, y produce un resumen de mensaje de 160 bits. Este
algoritmo consta de cinco pasos fundamentales.
En el primer paso, se añade un
bloque de relleno, aunque no sea necesario, para que el mensaje tenga una longitud
igual a 64 bits menor que un múltiplo de 512 (448 mod 512); el primer bit de relleno
es un 1, y el resto son 0. Como segundo
paso, se añade un bloque de 64 bits, que contiene la longitud del mensaje
original sin relleno. Con esto, se tiene un mensaje con longitud igual a un múltiplo
de 512 bits. El tercer paso es inicializar cinco bloques de 32 bits, conocido
como búfer MD, con los cuales se obtendrán valores intermedios y finales de la
función hash.
El cuarto paso, o función de
compresión, es el más importante y complejo, en donde se procesan los bits. Consta
de 4 etapas, de 20 pasos cada una, aunque cada una usa una función lógica
diferente para tratar los datos. En cada etapa se toma un bloque de 512 bits y
el valor del búfer de 160 bits, el cual se actualiza en cada etapa. También se usa
una constante diferente en cada etapa. La salida de 160 bits.
Es poco probable que, con el
SHA-1, dos mensajes aleatorios, aunque tengan regularidades similares, tengan
el mismo código hash. A menos que este algoritmo tenga alguna debilidad secreta,
la dificultad de dar con dos mensajes con el mismo resumen es del orden de 280
operaciones, mientras la dificultad de encontrar un mensaje con un resumen dado
es del orden de 2160 operaciones.
Figura 1. Algoritmo SHA-1. Tomada de Fundamentos de Seguridad en Redes.
Otro algoritmo importante es el
MD5, desarrollado por Ron Rivest. Era el algoritmo más utilizado hasta el
surgimiento del SHA-1, pues éste toma una entrada de 512 bits y devuelve una
salida de 128, a comparación de los 160 del SHA-1, garantizando menor seguridad
debido al constante aumento de la velocidad de los procesadores. Se necesitan 264
operaciones para encontrar 2 mensajes iguales, y 2128 para obtener
un mensaje a partir de su resumen, cantidades menores que aquellas del SHA-1.
El RIPEMD-160 fue desarrollado en
el proyecto RIPE en Europa, por un grupo de hackers que lograron encontrar
debilidades en el MD5. Su versión original fue modificada luego de que un
programador ajeno al proyecto lograra encontrar debilidades en él. Es muy
similar al SHA-1, pues recibe datos en bloques de 512 bits y devuelve resúmenes
de 160.
El último algoritmo, HMAC, fue desarrollado
para implementar un código hash criptográfico, es decir, que utilicen una clave
secreta. De hecho, se le ha dado un mayor interés a este tipo de funciones, pues
son más fáciles de implementar que un cifrado convencional, están disponibles
en librerías, y no tienen restricciones de exportación, como ciertos algoritmos
de cifrado.
Debido a ello, se creó tal
algoritmo, HMAC, para satisfacer ciertos objetivos derivados de lo anterior,
como usar las funciones hash que se ejecutan bien en software, con código
gratis y fácil de conseguir, sin modificaciones; permitir la sustitución fácil
de funciones en caso de que se encuentren o necesiten más rápidas o seguras; preservar
el funcionamiento original de funciones sin incurrir en modificaciones significativas;
usar y manejar claves de forma sencilla; entre otras.
El algoritmo del HMAC se resume
en la siguiente fórmula:
HMACK (M)
= H[K+ XOR opad)||H[K+ XOR ipad)||M]]
Lo que se traduce, muy
burdamente, como la aplicación de la función hash a la concatenación de una
clave rellena de ceros XOR la constante opad, con la concatenación de dicha
clave XOR la constante ipad y el mensaje original.
Figura 2. Algoritmo HMAC. Tomada de Fundamentos de Seguridad en Redes.
Conclusión
En mi opinión, es más fácil la utilización de
las funciones hash si el objetivo es únicamente garantizar que el emisor de un
mensaje es quien dice ser, pues, si también se desea asegurar la
confidencialidad de la información, las funciones hash no nos sirven de nada,
pues sólo generan un resumen final de los datos, más no cifran como tal el texto.
Aunque el cifrar todo el texto, ya sea con
cifrado simétrico (clave secreta) o asimétrico (claves privada y pública),
garantiza que el emisor de un texto es auténtico, pues dicho texto no podría ser
descifrado con una clave que no sea la secreta compartida o la privada del
emisor, respectivamente, el uso de una función hash es, como ya se ha señalado,
una alternativa mucho más viable, pues se evita la actividad de compartir
claves, se reducen costos de hardware y tiempos de software, y se cumple con el
objetivo de la autenticación.
A mí me gustaría haber visto este tema un poco
más a detalle, pues se me hace interesante y más sencillo que la mayoría de los
algoritmos de cifrado; pero, a pesar de ello, creo que aún prefiero el uso de
dichos algoritmos, pues son más seguros y complejos para lograr su cometido de
autenticar usuarios.
Fuentes bibliográficas
- Stallings, Williams. Fundamentos de Seguridad en Redes: Aplicaciones y Estándares (segunda edición). Pearson Educación, S.A. Madrid, 2004. Págs. 59-71.
- www.segu-info.com.ar/proyectos/p1_hash.htm
- www.uco.es/servicios/biblioteca/CursosP/practicahash2.pdf
- www.criptored.upm.es/intypedia/docs/es/video14/DiapositivasIntypedia014.pdf
Comentarios
Publicar un comentario