¿Podemos fiarnos de los textos escritos por matemáticos?

Hoy os traigo algo que aunque hace tiempo que se produjo no había aparecido todavía por aquí. Es la respuesta de Rubén, de Automatic Human Behaviour la entrada Sólo con el ordenador no es suficiente que escribí hace un tiempo. He tomado prestado el título original de su post y el texto íntegro del mismo (él me dio permiso vía mail para hacerlo). La url del artículo en su blog es esta.


¿Podemos fiarnos de los textos escritos por matemáticos?

El artículo de hoy pretende ser una respuesta al texto, ¿Podemos fiarnos de los cálculos efectuados con ordenador? escrito por Óscar Ciaurri y Juán Luis Varona y publicado en La Gaceta de la Real Sociedad Matemática Española. Existe una versión en pdf y Diamond, de Gaussianos, publicó una versión resumida en su blog.

Mi hipótesis de partida es que este texto -si bien siempre es útil detectar fallos y errores comunes para que otros no los cometan- esta basado, parcialmente, en falacias con respecto al funcionamiento de los ordenadores y, lo que es peor, de las matemáticas que se emplean dentro de ellos.

Mi objetivo no es rebatir el texto original desde un blog, si no dar al lector las herramientas para comprobar por si mismo algunas de las falacias que he comentado y, de paso, hacer un poco de divulgación científica, que nunca viene mal.

Para empezar, vamos a presentar un modelo teórico que aproxima bastante bien las capacidades y, sobre todo, las limitaciones de cálculo de un ordenador. Es la conocida como, máquina de Turing.
Esta máquina no es mas que un robot que es capaz de procesar una cinta de datos codificados como unos y ceros. En cada instante, el robot puede leer o modificar el dato que tiene en el cabezal. La decisión se basa en un programa que, junto con los datos que lee, van cambiando el estado interno del robot.

De este modelo teórico, vemos dos cosas que se aplican a todos los ordenadores:

1) Los ordenadores solo son capaces de procesar números. Cualquier cosa que queramos que procesen, la tendremos que transformar a 1s y 0s. Un sonido lo tendremos que transformar en una secuencia de números. Una imagen también pasa a ser una secuencia de números. El texto también son números. Un ordenador no sabe leer, solo sabe contar. Todas estas conversiones se basan en convenios que habremos de decidir de antemano.

2) Los ordenadores -al menos los de un solo núcleo- procesan la información de manera secuencial. Esto tiene una implicación muy importante a la hora de determinar la complejidad de un problema. Por ejemplo, si el ordenador tiene que encontrar el camino óptimo entre una serie de rutas, tendrá que recorrerlas todas antes de estar totalmente seguro de que la que decida sera la óptima.

En determinadas situaciones, y partiendo ciertas intuiciones o información previa podemos obtener soluciones más eficientemente. También se puede buscar una solución que no sea la óptima, pero que en la práctica sea lo suficientemente buena. Sin embargo, en un caso general, no se pueden asumir dichas simplificaciones.

En el peor de los casos, podemos encontrarnos con problemas totalmente irresolubles, como el problema de parada, es decir, saber si un programa (con bucles, saltos e interrupciones) se va a parar o por el contrario, quedaría atrapado en un bucle que se ejecuta continuamente (lo que se llama un bucle infinito). La única forma de saberlo, es ejecutando el programa entero, con lo que si el programa tiene un bucle infinito, el programa quedara atrapado y nunca nos dará la solución.

3) También existe limitaciones a nivel práctico. El robot de Turing puede estar trabajando por tiempo indefinido hasta resolver casi cualquier problema (como hemos dicho cualquiera que tenga solución, lo que se llama un problema decible). Sin embargo, en la práctica, existen muchos otros problemas que no se pueden resolver por un ordenador normal, ya que son problemas intratables. La wikipedia pone el ejemplo de los problemas con complejidad exponencial:

Para ver por qué las soluciones de tiempo exponencial no son útiles en la práctica, se puede considerar un problema que requiera 2n operaciones para su resolución (n es el tamaño de la fuente de información). Para una fuente de información relativamente pequeña, n=100, y asumiendo que una computadora puede llevar a cabo 1010 (10 giga) operaciones por segundo, una solución llevaría cerca de 4*1012 años para completarse, mucho más tiempo que la actual edad del universo.

4) Otra limitación técnica viene del hecho de que la memoria (el tamaño de la cinta), no es infinita. De hecho, para almacenar cualquier posible número, necesitaríamos una cadena arbitrariamente larga de 1s y 0s. Eso no solo aumenta el coste de memoria, si no también el coste computacional de procesar un único número. De este modo, se suele limitar el tamaño de los números a 8, 16, 32 o 64 bits. Puede parecer que 64 bits dan mucho juego (son 264 números), y de hecho, lo dan, pero recordemos que los números naturales son infinitos números. Y tan lejos del infinito esta un googol como el 1. Pero es que además, como vimos en otros articulos, los números reales son un infinito de segundo orden, es decir, en el intervalo que hay entre cada uno de los infinitos números enteros, hay infinitos números reales, cada uno con potencialmente infinitos decimales. ¿No parecen demasiados para representarlos con 264 números? Pues se hace, pero con el consiguiente error asociado que hay que tener en cuenta.

En resumen, hay muchos problemas que para nosotros son triviales, pero que para un ordenador como los que utilizamos habitualmente, son imposibles ya que: requieren un tiempo de cálculo enorme, requiere una cantidad de recursos impracticable o simplemente, no existe ninguna forma de que el ordenador obtenga un resultado.

Para terminar con los preliminares, quisiera añadir un pequeño trasfondo de lo que es la Ingeniería de Software.

El software ha de pensarse que es como un producto más. Por ejemplo, podemos compararlo con un coche.

A principios del siglo XX, los vehículos a motor estaban todavía en fase de desarrollo. Los pocos vehículos que circulaban por las carreteras tenían continuos fallos y taras. Era raro poder circular más de 10 kilómetros sin que se gripase el motor, se fundiese alguna lampara o se pinchase una rueda. El mundo tampoco estaba preparado para ellos, y parte de los problemas provenían de carencia de pavimento en las carretas, falta de señalización, etc.

Sin embargo, a pesar de los avances que se han dado a lo largo del siglo XX (de todos es sabido que la industria de la automoción es una de las que más dinero mueve a nivel mundial), solo recientemente se han creado e implantado extensivos controles de calidad y diseños exhaustivos que otorgan una gran calidad al producto final y una garantía de seguridad.

Se tardó un siglo en desarrollar e implantar toda esa tecnología.

Por otro lado, a pesar de los avances que ha sufrido el campo de la automoción, no le pedimos a un coche que vuele, por mucho que lo utilicemos para viajar, y volar sea una forma eficaz de hacerlo. Incluso si alguien utiliza un motor de coche para volar, no es la mejor forma de hacerlo. Es una falacia razonar que si un elemento se utiliza para un fin, ha sido diseñado para ese propósito.

Por ejemplo, por mucho que utilicemos los ordenadores para cálculo simbólico, el modelo de ordenador de von Neumann, que aun hoy utilizamos, se diseñó para calculo numérico. Y punto. Cualquier algoritmo que resuelva problemas simbólicos será porque primero los convierte a problemas numéricos.

La Informática como ciencia y como tecnología, es mucho mas joven que la automoción. Sin embargo, ya se están empezando a implantar controles de calidad dignos de las grandes compañías de vehículos. Casi desde el principio de la programación, han existido los betatester (gente que se dedica a probar y sacar los fallos de un programa al final de su desarrollo), se han desarrollado técnicas de métodos formales y análisis de software para reducir al mínimo los errores.

Sin embargo, siempre aparecen errores. Al igual que en los vehículos siguen apareciendo fallos de diseño (como el famoso Mercedes que hace pocos años tuvo que ser retirado del mercado porque en caso de accidente, el motor se incrustaba en el habitáculo de pasajeros). Por desgracia, el software es algo que se maneja jerárquicamente. Aunque no nos demos cuenta, en todo momento estamos ejecutando varias piezas de software (programas de trabajo, sistemas operativos, drivers, controladores…) que a su vez están basados en otras piezas de software (compiladores, interpretes…). Simplemente con que falle solo uno de esos elementos, el sistema falla. Y lo más probable es que, a fecha de hoy, alguna de esas piezas de software estén todavía hechas con métodos antiguos de programación y sin los controles de calidad que hoy se utilizan. ¿Alguien se atrevería a conducir en una autopista donde, al fallar cualquiera de los vehículos que van en ella, automáticamente fallaran todos? ¡Estaríamos arreglando pinchazos cada 100 metros!

Pero en todo este panorama, los programadores tenemos una ventaja que la automoción no tendrá nunca, los demostradores de teoremas. Un demostrador de teoremas es un programa que nos garantiza, matemáticamente, que nuestro trozo de código hace exactamente lo que queremos que haga. Es decir, nos garantiza que matemáticamente es correcto, perfecto. Por desgracia, los demostradores de teoremas todavía se encuentra en fase de investigación y sus capacidades, a día de hoy, son muy limitadas. Realmente, la dificultad de un demostrador de teoremas, deriva de que es un cálculo simbólico, no numérico.

Ahora, vayamos por partes a resolver algunos de los puntos que comentan los autores. Como he dicho antes, no es mi idea rebatir el texto completo, así que me centrare en algunos de los puntos que se resumen en el blog de Gaussianos.

1) Cálculo de limites:

Los autores denuncian que una función cuyo limite en determinado punto varia si el limite se toma “por arriba” o “por abajo” no es resuelto como tal por Mathematica, ya que si le damos a calcular el limite, sin definir por donde se mira, nos devuelve el valor por arriba y no nos avisa de que esta indefinido.

Solo hace falta ir a la documentación de Mathematica y leer:

The value of Sign[x] at x=0 is 0. [..] Its limit, however, is 1. The limit is by default taken from above.

Es decir, Mathematica sí que nos avisa de que va a coger el límite “por arriba”. En muchos otros ejemplos del articulo, la crítica es la misma: el programa no nos informa de lo que hace. Eso es totalmente falso, porque como lo hemos visto, si que informa, aunque en la documentación. Lógicamente, un software de esa magnitud no puede estar informando de cada acción que haga. ¿Se imaginan los lectores un navegador de internet que cada vez que pulsara en un link le saliese un mensaje:

“Acaba de pulsar un link. Esto le enviara a otra pagina y dejará atras la página que esta leyendo. ¿Desea continuar?”

Acabaríamos todos de los nervios. Lo primero de todo, antes de usar un software, antes de usar cualquier herramienta, es leerse el manual. Eso lo sabe cualquier técnico y debería saberlo cualquier usuario de software. De hecho, existe un programa que se diseñó para intentar informar al usuario bastante a menudo, a sabiendas de que no se leería la documentación por su cuenta. El programa era el asistente de la ayuda de Microsoft Office, más conocido como Clippo. El odio que suscitó es tal, que existen hasta videojuegos cuyo único objetivo es aniquilar el personaje animado de la forma mas cruel posible.

2) Gráficos ficticios:

Decir que en este caso, gran parte del error que se comete no es de los autores originales, si no del resumen de Gaussianos.

En este caso, los autores protestan porque el programa no representa bien según que gráficas, haciendo clara referencia, aunque no explícita, al teorema de Niquist-Shanon.

Para empezar, decir que un ordenador, jamas podrá dibujar una gráfica continua, ya que por definición, tiene infinitos puntos. Y como hemos visto, para un ordenador, infinito es 264. Un ordenador siempre es discreto. De todos modos, aunque la pudiese representar, nunca la podría sacar por pantalla, ya que siempre tendríamos la limitación de los píxeles, o en último término, del ojo humano.

Pero aun así, en este caso, los autores originales claramente comentan que el software Mathematica puede resolver este problema hasta cierto punto. Por la descripción que hacen de la método que usa Mathematica, se están refiriendo al potente algoritmo de bootstrapping. Este algoritmo, aunque fundamentado en una solida base matemática, se puede explicar de manera bastante sencilla: En caso de que las muestras que estemos tomando no sean suficientemente representativas, podemos usar las que tenemos para obtener información sobre la función y así tomar más muestras en determinadas zonas “de manera inteligente”. De este modo se consigue mejorar la calidad del resultado con menos coste añadido.

Por desgracia, el algoritmo de bootstrapping es un algoritmo con coste exponencial. Es decir, cuando aumentamos el número de dimensiones, el coste aumenta enormemente hasta hacerlo intratable, como veíamos antes. Lógicamente, cuando un usuario le da al botón para dibujar una función, no quiere que pasen años o siglos antes de poder verla. Es por ello, que Mathematica ha limitado el uso del bootstrapping a gráficas de una sola dimensión, donde el tiempo de cálculo, entra dentro de lo razonable. Este nimio detalle es contemplado en el articulo original, pero en el resumen de Gaussianos, inexplicablemente, se perdió.

3) Simplificar

Este punto y otros por el estilo donde se habla del cálculo simbólico directamente no tienen sentido. Todos los razonamientos se basan en la premisa de: “Dado que esas operaciones son triviales para cualquiera, también lo deberían ser para la máquina.”

Bien, y yo me pregunto: ¿Por qué? Hemos visto que hay muchos problemas que son triviales para nosotros y no para un ordenador. Otros son triviales para el ordenador y tremendamente complejos para nosotros. Simplemente funcionamos distinto. De hecho, cuando se crearon originalmente, se crearon con la idea de complementarnos, luego se especializaron en lo que se nos da mal a los humanos. Lógico, ¿no creen?

Además, los autores de Mathematica, dado que el calculo simbólico es muy costoso y ha de probar muchos caminos y opciones, han optado por dar una solución práctica. Han cogido las operaciones más rápidas y que aparecen más frecuentemente a la hora de simplificar y las han incluido en una función. Esta función tiene la ventaja de ser muy rápida, pero no te garantiza un resultado satisfactorio. Luego existe otra función que tiene una biblioteca de operaciones mucho más extensa y por lo tanto da mejores resultados, pero más lento.

Es como cuando nos vamos a comprar un libro, que primero leemos el resumen, y aunque no nos garantiza que el libro sea bueno o malo, si que en algunos casos nos puede servir de ayuda.

Esto no es una solución matemática, ni tiene ninguna base teórica. Simplemente se ha hecho así por comodidad del usuario. Prueba primero la rápida, y si no funciona, siempre podrás probar la lenta, pero si te funciona, eso que te has quitado de encima. Tiene sentido, ¿no?

Pero no sabemos como han escogido los programadores que operaciones poner en la rápida y cuales no. Y no existe ninguna justificación matemática. Hacer suposiciones con la premisa: “esta operación es muy sencilla, debería ser resuelto por la función resumida” simplemente no tiene ni pies ni cabeza.

4) Fallos de código:

Esta parte es la única que no esta basada en falacias. Es normal que haya fallos en un código, al igual que es normal que haya fallos en cualquier producto. No es deseable, pero somos humanos. Me parece una labor encomiable que se busquen esos errores y se hagan públicos a una comunidad que usa ese software masivamente. Incluso la idea de anunciar los fallos de versiones antiguas, ya que mucha gente no actualizara su software a menudo, al ser software de pago.

Desconozco si Mathematica ofrece actualizaciones gratuitas de las correcciones de software, aunque muchos de los programas comerciales sí lo hagan. Normalmente, aunque no nos demos cuenta, cuando se compra un software, muchas veces se compra también el soporte adicional.

Por otro lado, lo que veo un error es escribir el texto a modo de denuncia en vez de simplemente informativo. De hecho, muchos de esos fallos que se comentan se han corregido en las últimas versiones, lo cual es loable y no denunciable. Además en vez de denunciarlo en una revista española que no leerán los programadores, se puede contactar con ellos. Es muy probable que corrijan los fallos en la próxima versión e incluso nos regalen alguna suscripción gratuita por haberlos encontrado.

En este punto, es admirable la labor de las comunidades de software libre, donde puedes informar del error, que normalmente es subsanado a las pocas horas y, al día siguiente, puedes descargarte el nuevo código perfectamente arreglado.

Mi conclusión es que sí podemos fiarnos de los cálculos de un ordenador, pero no podemos fiarnos de los usos y decisiones que tomemos a posteriori.

Nota: Como punto final, me gustaría comentar que no tengo ninguna implicación con Mathematica ni con la compañía que lo ha desarrollado. Simplemente ha sido la herramienta en la que estaba basada el texto original. Personalmente, y dado que mis aplicaciones van más orientadas al cálculo numérico, prefiero Matlab. Como alternativa de software libre y gratuita, existe Octave, que si bien tiene alguna capacidad reducida, es un serio competidor. También existen lenguajes de programación orientados al cálculo científico con excelentes bibliotecas de apoyo, como por ejemplo R (para cálculo estadístico) y Python con SciPy (más general).


Como habéis visto Rubén me dio la réplica con este artículo y, aunque con muchísimo retraso, quería ponerla aquí. Espero vuestros comentarios sobre el asunto, pero, por favor, con la mayor educación posible tanto para hacia Rubén como hacia mí. Aviso ésto porque sé que estos temas a veces se salen de madre y pueden llegar a límites que no estoy dispuesto a aceptar. De todas formas estoy seguro de que todos sabremos mantener la compostura.

Sólo con el ordenador no es suficiente

Introducción

En los tiempos que corren los programas informáticos de Matemáticas son fundamentales para el trabajo de cualquier persona relacionada con ellas: estudiante, profesor, investigador…Los paquetes informáticos de los que disponemos en la actualidad (Matlab y Mathematica por ejemplo) son realmente buenos y completos. Con ellos podemos realizar todo tipo de operaciones, ya sean numéricas, simbólicas, gráficas…El potencial de estos programas es inmenso.

Visto esto mucha gente puede llegar a pensar que de una forma u otra los conocimientos matemáticos pierden importancia frente a estos programas. ¿Para qué necesitamos realizar cálculos numéricos largos y engorrosos si el programa nos los hace en muy poco tiempo y sin rechistar? ¿Por qué realizar operaciones simbólicas complicadas si el programa las resuelve con gran facilidad? ¿Por qué dibujar gráficas que siempre quedarán imperfectas cuando el programa las representa a la perfección?

(Leer el resto del post)

¿Sabía que…

…el descubridor del famoso error FDIV de los microprocesadores Pentium fue un matemático? Pues sí. Concretamente fue Thomas R. Nicely.

En junio de 1994, el profesor Thomas R. Nicely del Lynchburg College, enfrascado en un estudio sobre la constante de Brun (relacionada con los primos gemelos), observó que al hacer ciertos cálculos obtenía resultados inconsistentes. Comenzó a eliminar factores que pudieran provocarlos (por ejemplo, el software) y en octubre del mismo año comunicó su descubrimiento a Intel. Por ello la compañía se vio obligada a reemplazar de forma gratuita todos los procesadores defectuosos.

Para que luego digan que las Matemáticas no sirven para nada.

- Pentium FDIV Bug en la Wikipedia (en inglés)

Algoritmos HASH (II): Atacando MD5 y SHA-1

Este artículo es una colaboración enviada por LordHASH

Algunos de los algoritmos de HASH más utilizados, que son sobre los que trabajaremos, son los siguientes:

  • MD5 (Message-Digest Algorithm 5 o Algoritmo de Firma de Mensajes 5): Desarrollado por Ron Rivest, ha sido hasta los últimos años el algoritmo hash más usado. Procesa mensajes de una longitud arbitraria en bloques de 512 bits generando un compendio de 128 bits. Debido a la capacidad de procesamiento actual esos 128 bits son insuficientes, además de que una serie de ataques criptoanalíticos han puesto de manifiesto algunas vulnerabilidades del algoritmo. Puede ser útil para comprobar la integridad de un fichero tras una descarga, por ejemplo, pero ya no es aceptable desde el punto de vista del criptoanálisis.
  • SHA-1 (Secure Hash Algorithm 1 o Algorimo de Hash Seguro 1): El SHA-1 toma como entrada un mensaje de longitud máxima 264 bits (más de dos mil millones de Gigabytes) y produce como salida un resumen de 160 bits. Este número es mayor que el que se utilizaba en el algoritmo SHA original, 128 bits. Ya existen nuevas versiones de SHA que trabajan con resúmenes de 224,256,384 e incluso 512 bits.

En realidad, lo seguros o inseguros que estos algoritmos sean no depende de los conocimientos informáticos o telemáticos que uno tenga, sino de sus conocimientos matemáticos. Nuestra intención es demostrar por dónde cojean los algoritmos de HASH, la dificultad computacional que presentan, y qué soluciones se dan a los posibles ataques que puedan sufrir por parte de individuos malintencionados.

Desde el año 2004 aproximadamente, cuando saltaron las primeras noticias escandalosas sobre la ruptura de MD5, la seguridad que ofrecen los algoritmos de HASH a nuestros esquemas de cifrado ha sido una cuestión que se ha puesto en entredicho. ¿Qué seguridad ofrecen estos algoritmos? ¿Resulta computacionalmente complejo romper uno de estos algoritmos? ¿Qué solución se debe adoptar? Intentaremos resolver estas cuestiones.

Intentemos dar una descripción algo más matemática de lo que es una función HASH. Supongamos que tenemos un mensaje a, al que aplicamos una función resumen a la que llamaremos h. Decimos entonces que el resultado de esta operación, al que llamaremos b es el HASH de a. Es decir:

h(a)=b

Esta función debe ser sencilla de realizar para un computador, pero debe ser computacionalmente imposible realizar la operación inversa, al menos para usuarios normales.

Además, esta función tiene otra característica: el tamaño de la entrada no es de longitud fija, puede ser de longitud variable. Esto tiene la siguiente consecuencia, que no demostraremos matemáticamente, pero que asumiremos por estar razonado en otros artículos publicados en Internet (al final se indican): es posible que dos mensajes de entrada a produzcan el mismo mensaje de salida b. Es decir, es posible encontrar un mensaje c, tal que:

h(c)=b

Sin embargo, encontrar ese mensaje debe ser, al igual que la particularidad antes mencionada, muy complejo desde el punto de vista computacional. Para los algoritmos de HASH esto es lo que se conoce como colisión: que dos mensajes de entrada produzcan el mismo mensaje de salida.

Así, a priori, podemos establecer dos posibles vulnerabilidades de las funciones HASH:

  • Que sea posible realizar la operación:

    h-1(b)=a

    Habitualmente, a la operación de invertir la función HASH comprobando todas las posibilidades para los bits de salida se le llama ataque de fuerza bruta. Esto es lo que debe ser computacionalmente impracticable. Supondría aplicar la función HASH 2n veces hasta encontrar la coincidencia (n es el número de bits de salida de la función).

  • Que se hallen colisiones:

    h(a)=b y h(c)=b, a distinto de c

    Lo que antes hemos denominado colisión.

Estas dos posibles debilidades dan lugar a cuatro tipos de ataques:

  • Ataque Tipo 1: El atacante es capaz de encontrar dos mensajes al azar que colisionan pero es incapaz de hacerlo de forma sistemática. Si es capaz de dar sólo con dos mensajes que provocan colisión, esta no es razón suficiente para tildar el algoritmo de ineficiente. Índice de peligrosidad: *
  • Ataque Tipo 2: El atacante es capaz de generar dos mensajes distintos de forma que sus HASH colisionen, pero sin saber a priori qué hash resultará. Es decir, el atacante no podría generar “queriendo” el HASH que necesite para fines maliciosos. Índice de peligrosidad: **
  • Ataque Tipo 3: El atacante es capaz de construir un mensaje sin sentido de forma que su HASH colisione con el de un mensaje con sentido. Si éste es el caso, el agente malicioso puede atacar algoritmos de encriptación asimétricos con firma digital, haciendo que se firmen mensajes sin sentido, y que el destinatario los acepte como fidedignos. Índice de peligrosidad: ***
  • Ataque Tipo 4: El atacante es capaz de crear un segundo mensaje falso que tiene sentido y cuyo hash colisiona con el del mensaje verdadero. En este caso, el atacante puede actuar con total impunidad, puede falsificar certificados, firmar mensajes…El resultado sería desastroso. Índice de peligrosidad: ****.

El problema entonces es el siguiente: ¿cómo de difícil es encontrar una solución? ¿Qué ataques reales son practicables? ¿Qué se gana incrementando el número de bits de salida del algoritmo?

En primer lugar, responderemos a la última pregunta. Si aumentamos el número de bits de salida del algoritmo, el ataque de fuerza bruta será más impracticable y también lo será encontrar los mensajes que colisionen, pues teóricamente se cumple que para confiar en que podemos encontrar dos mensajes que colisionen no hay que realizar 2n operaciones, si no sólo 2n/2.

Realicemos algunos cálculos para realizar ataques de fuerza bruta:

  • Para una clave de 12 dígitos, escrita con un teclado con 97 caracteres (base 97), habría que realizar (esto no tiene nada que ver con los algoritmos de HASH):

    9712 = 693.842.360.995.438.000.295.041 comprobaciones.

  • Para MD5, la salida es de 128 bits, sería necesario realizar:

    2128=3′402823669 * 1038 operaciones.

Trabajemos ahora con los ataques basados en búsqueda de colisiones:

  • Para MD5, la salida es de 128 bits, luego hay que operar sobre la mitad de bits, y sería necesario realizar:

    264=18.446.744.073.709.551.616 operaciones.

  • Para el algoritmo SHA 1, cuya salida es de 160 bits:

    280=1.208.925.819.614.629.174.706.176 operaciones.

    Curiosidad: 1.000.000 de ordenadores capaces de procesar en 1 µs cada operación tardarían más de 38.000 años en las 280 operaciones.

Y para los más desconfiados e incluso paranoicos: ¿qué hay de las supercomputadoras y de la gente que sí dispone de los medios necesarios? Cuando saltaron las primeras alarmas sobre estos algoritmos, hace unos dos años, las cifras eran las siguientes:

  • Para romper el SHA-0 completo se ha requerido un supercomputador de BULL de 256 procesadores durante unos 9 años de proceso, pero al supercomputador que está instalando IBM en la UPC (Barcelona) sólo le costaría del orden de 1 año.
  • Otro grupo de investigadores, Wang, Feng, Lai, y Yu han reportado haberlo conseguido con una complejidad aproximadamente 2000 veces menor (240 en vez de 251). Esta reducción equivaldría a una necesidad de cálculo de algo menos de 1 día, si la relación fuese lineal, pero los mismos investigadores han reportado necesitar sólo 1 día con un IBM P690 en cluster, para romper el MD5, que tiene una complejidad equivalente.

Por tanto, lo habitual no es que nos ataque desde uno de estos grandes usuarios (tienen cosas más interesantes que hacer, diría yo…) si no que nos ataque un cracker o similares (ACLARACIÓN: No incluyamos a los señores programadores en esto, los hackers. Gracias a Richard Stallman).

Lo habitual es que este tipo de usuarios realicen ataques basados en diccionarios, como la aplicación para Ñu/Linux John the Ripper. Este tipo de aplicaciones tiene una base de datos con claves comunes, que prueban sobre los sistemas a los que queremos acceder (por ejemplo Sistemas basados en UNIX donde se almacenan los resúmenes HASH de el nombre de usuario y su clave para autenticar). Ante esto sólo hay una solución: EVITAR LAS PASSWORDS ABSURDAS. No sirve (marta -tkm ni maria-secreto) ok??

Concluyendo, dependiendo de su nivel de paranoia críptica y de la aplicación que estén utilizando…escojan su algoritmo de HASH, pero no acepten menos de SHA-1. Cuando un algoritmo empieza a presentar vulnerabilidades no tarda mucho en ser aniquilado, así que a algunos de estos les queda poco tiempo de vida.

Fuentes:

Ir a Algoritmos HASH (I): Introducción

Algoritmos HASH (I): Introducción

Este artículo es una colaboración enviada por LordHASH

En primer lugar, trataremos de abordar de forma sencilla este concepto para aquellos que no lo conozcan. Podemos decir que un HASH no es más que un número resumen. De hecho, en muchos sitios web podéis encontrar expresiones como “checksum MD5″, lo que literalmente se traduce por “suma de comprobación”. Así, el concepto no es complicado, pero sí su implementación. Pongamos un ejemplo: supongamos que tenemos un fichero cualquiera. Pues bien, si consideramos dicho fichero como un flujo de bits y le aplicamos un algoritmo de HASH lo que obtenemos es otro conjunto de bits (de longitud fija y que depende del número de bits de salida del algoritmo o función que utilicemos) que depende bit a bit del contenido del flujo original de bits que sirvió como entrada al algoritmo.
Además, cumplen las siguientes propiedades:

• Todos los HASHes generados con una función de hash tienen el mismo tamaño, sea cual sea el mensaje utilizado como entrada.
• Dado un mensaje, es fácil y rápido mediante un ordenador calcular su HASH.
• Es imposible reconstruir el mensaje original a partir de su HASH.
• Es imposible generar un mensaje con un HASH determinado.

Es decir, un algoritmo de HASH no es un algoritmo de encriptación, aunque sí se utiliza en esquemas de cifrado, como algoritmos de cifrado asimétrico (por ejemplo en el RSA).

Ahora bien, tener una función de estas características puede tener muchas aplicaciones. Algunas de ellas pueden ser las siguientes:

  • Comprobación de integridad de ficheros: Supongamos que queremos transmitir un fichero a un amigo. Si antes de realizar este envío calculamos la función HASH del fichero, para nuestro amigo del otro extremo es posible verificar la integridad del fichero aplicando el mismo algoritmo al archivo que recibe. Si ambos coinciden, podemos asegurar que el envío ha sido satisfactorio. Ésta es una aplicación real que se utiliza, por ejemplo, para comprobar la integridad de muchos paquetes que se descargan en distribuciones del sistema operativo GNU/Linux.
  • Seguridad en procesos de identificación en sistemas: Los procesos de identificación (Login+Password) se ven reforzados por estos algoritmos. Se utilizan de la siguiente forma: cuando un usuario accede a su computadora debe introducir su nombre de usuario y su password. Pues bien, si el sistema operativo no registra estos datos como “texto claro”, si no que registra el resultado de aplicarles una función HASH, en el caso de que un usuario malicioso logre acceder a nuestro archivo de registros no conseguirá (a menos que el algoritmo utilizado sea malo o disponga de una supercomputadora) revertir el contenido de dicho registro, y por tanto no puede acceder a nuestro sistema. Esta misma idea se aplica en identificación de usuarios en muchas webs, con la diferencia de que para que este esquema sea seguro debe incluir información adicional y “aleatoria”, como marcas de tiempo y redundancias.
  • Firma digital: Estos algoritmos se utilizan en esquemas de firma digital para verificar la integridad de la información enviada por el canal de comunicaciones. Algoritmos de cifrado asimétrico, como RSA por ejemplo, realizan lo siguiente: calculan la función HASH del contenido del mensaje que se va a enviar y luego se firma dicho checksum con la clave privada del emisor. Así se asegura la integridad de la información y el “no repudio”.
  • En el próximo post veremos algo más sobre ataques a dos algoritmos HASH: MD5 ySHA-1.

    Ir a Algoritmos HASH (II): Atacando MD5 y SHA-1

Problemas de programación

Aunque no parezca que esto tiene mucho que ver con la temática del blog, la tiene.

La Universidad de Valladolid tiene una web en la que propone unos problemas a resolver programando en cualquier lenguaje (o eso creo) de programación, para luego enviárselo y una vez revisado aparecer en un ranking según bien o mal tu solución.

No deja de ser curioso que la mayoría de los problemas que he visto (he visto pocos) son matemáticos, incluso muchos de ellos los hemos visto en este blog.

Yo creo que me voy a apuntar a ver si hago algunos, aunque cada vez que pienso lo que desaprovecho el tiempo y lo que luego me quejo de tener poco tiempo (viva la procrastinación).

(Vía meneame, encontrado de casualidad haciendo una búsqueda un tanto absurda)
(Para quién no lo sepa, el blog está un tanto abandonado por la falta de tiempo comentada y sí este tema salió en meneáme hace ya cuatro meses)

Criptografía: Resumen

Para cerrar totalmente la serie de posts sobre criptografía, voy a realizaros una especie de índice desde el cual podáis acceder a cada post.

Criptografía: Protocolo de distribución de clave BB84

El cifrado de Vernam

El protocolo de cifrado que se usa en criptografía cuántica es posiblemente el más sencillo de todos y hasta ahora, el único que se ha demostrado que es irrompible, el cifrado de Vernam, o One Time Pad. Como ya se ha explicado anteriormente, no me extenderé demasiado, solamente diré que consiste en una clave 100% aleatoria (no vale pseudoaleatoria) de igual longitud que el mensaje y que lo único que hay que hacer para cifrar es un XOR con el mensaje y la clave. ¿Cuál es el problema? Que solo se puede usar una vez, porque si usáramos dos veces la misma clave, el problema de encontrar el texto en claro sería trivial para cualquier criptoanalista. Entonces, si no podemos usar la misma clave dos veces, tendremos que hacer llegar la clave al receptor de alguna manera, o bien quedando con él antes o a través de un canal seguro. La idea del canal seguro es inútil, porque si de verdad exisitiera no tendríamos ni que cifrar el mensaje, respecto a lo de quedar antes en persona, es lo que se solía hacer para usar este cifrado, como los cuadernos con claves de un solo uso que se usaban en la Segunda Guerra Mundial y que Stephenson narra perfectamente en su Criptonomicón. Pero hoy día, la opción de los cuadernos de un solo uso queda totalmente fuera de uso y es poco útil en comunicaciones industriales y operaciones que se realizan a diario.

En definitiva, tenemos el sistema ideal de cifrado, sencillo y eficaz, pero no podemos usarlo por un pequeño problema técnico a la hora de distribuir la clave. La mecánica cuántica viene a solucionar este problema proponiendo un método para distribuir una clave binaria, tan larga como se quiera, totalmente aleatoria y asegurándose de que solo el emisor y el receptor la poseen, justo lo que necesitamos.

(Leer el resto del post)

Project Euler: Matemáticas y Programación

Project Euler es una web donde podemos encontrar muchos desafíos que involucran matemáticas y programación. Se trata de una serie de problemas matemáticos que requieren casi obligatoriamente la creación de un programa para resolverlos. Por ejemplo:

Si el 2 es el primer número primo, el 3 el segundo, el 5 el tercero…encuentra el primo número 10001.

Podemos verlos todos sin necesidad de registrarnos, pero si nos registramos podemos ir sumando puntos conforme vamos resolviendo las cuestiones. Cada uno de los problemas comienza con 20 puntos cuando es propuesto y va bajando de puntuación conforme los usuarios van resolviéndolo. Yo he estado mirando unos cuantos, pero como mi nivel de programación es nulo no he podido hacer mucho. He resuelto uno, el problema número 9 en estos momentos:

Encuentra una terna pitagórica (a,b,c) tal que a+b+c=1000

Ese también lo podéis resolver vosotros. Buscad en este blog y encontraréis la información suficiente.

Y si vais resolviendo problemas podéis usar lo comentarios para informarnos y para dar o pedir ayuda. Seguro que los informáticos del blog estarán encantados.

Criptografía: Cifrado de clave pública II

Cifrado RSA

El algoritmo fue descrito en 1977 por Ron Rivest, Adi Shamir y Len Adleman (la sigla RSA es Rivest Shamir Adleman) en el MIT.

El cifrado RSA es un algoritmo de cifrado de clave pública (o asimétrico) por bloques, que como todos los cifrados de clave pública tiene dos claves: una pública, que se distribuye a los usuarios que quiera el propietario de ella, y otra privada, la cual es guardada en secreto por su propietario. Así cuando se envía un mensaje, el emisor usa la clave pública de cifrado del receptor para cifrar el mensaje y una vez que dicho mensaje llega al receptor, éste se ocupa de descifrarlo usando su clave oculta.

El algoritmo sigue los siguientes pasos:

  1. Se construye un número “N”, que resulta del producto de dos primos “p” y “q” (normalmente son números muy grandes). Teniendo N = p · q y Φ(N) = (p-1) · (q-1)
  2. Se selecciona un número “e”,1 < e < Φ(N), tal que MCD (e, Φ(N)) = 1 (”e” y Φ(N) son primos relativos).
  3. Se calcula el inverso de “e”, denotado por “d”, tal que e · d = 1 (mod Φ(N))
  4. Con esto se consiguen las claves (e, d), siendo la clave pública (e, N) y la clave privada (d, N).

Una vez tenemos las claves podemos pasar a cifrar/descfirar los mensajes:

  • Cifrado: C = Me (mod N) con MCD (M, N) = 1 y M < N
  • Descifrado: M = Cd (mod N)

La seguridad de este algoritmo radica en que no hay maneras rápidas conocidas de factorizar un número grande en sus factores primos utilizando computadoras tradicionales.

(Más información en Wikipedia)

(Leer el resto del post)

Anterior