Programa para probar funciones hash

Iniciado por Alvarito050506, 20 Octubre 2019, 22:06 PM

0 Miembros y 2 Visitantes están viendo este tema.

Alvarito050506

Hola a todos.

Estoy desarrollando una función hash y quiero probarla, al parecer mis scripts de pruebas no funcionan, ya que estuve semanas con una función que creía que 'A' == 'P' sin darme cuenta...  :rolleyes:

He aquí mi duda: ¿hay algún programa que implemente (todas) las pruebas de la competición SHA-3 del NIST sobre la función hash especificada?

Muchas gracias de antemano.

Serapis

Al decir que estás desarrollando una función hash, quieres decir una ingeniada por tí o la implementación de una función específica y conocida?.

Luego resulta parco decir: "quiero probarla" ... "al parecer mis scripts de pruebas no funcionan".

En qué consisten las pruebas y/o cuáles son?. Es decir si estás haciendo una función hash propia, qué importac ningún programa que no sabe nada de tu hash?.
Y si estás implementando una función hash conocida, cuál es y en qué parte te has perdido?.

Alvarito050506

Hola @NEBIRE, estoy diseñando una función propia, no implementando una.

Cita de: NEBIRE en 22 Octubre 2019, 19:20 PM
Luego resulta parco decir: "quiero probarla" ... "al parecer mis scripts de pruebas no funcionan".

Sinceramente no sé a que te referís con esto, si es a que es redundante decir que mis scripts de pruebas no funcionan, puede que así sea. Si, por el contrario, te referís a lo amplio que suena "quiero probarla", me refiero a que quiero ejecutar las pruebas del NIST.

Cita de: NEBIRE en 22 Octubre 2019, 19:20 PM
En qué consisten las pruebas y/o cuáles son?.

Las pruebas son las siguientes:

  • Resistencia a preimagen
  • Resistencia a segunda preimagen (colisiones)
  • Resistencia a la contribución de bits (agregar bits al mensaje)
  • Resistencia a la resta de bits (no me acuerdo el nombre real, quitar bits del mensaje)

Cada test tiene que repetirse de 2 a 4 veces la cantidad de bits de salida de la función, si no mal recuerdo. Los primeros dos son fáciles de implementar, donde me perdí es en los últimos dos, es decir ¿cómo es posible "agregarle" o "quitarle" bits al mensaje?, bytes es fácil, ¿pero bits? :o.

Luego planeo hacer mi "propias" pruebas de segunda preimagen, basadas en diccionarios que andan rondando por ahí.

Cita de: NEBIRE en 22 Octubre 2019, 19:20 PM
Es decir si estás haciendo una función hash propia, qué importac ningún programa que no sabe nada de tu hash?.
Si con esto te referís a qué importancia tiene probar mi función, no lo sé, la estoy desarrollando por hobby :rolleyes:. Si te referís a qué "importaría" al programa, sería una implementación de mi función (todo por ese "importac", perdón).

En fin, gracias por tu respuesta y perdón por la poca especificidad del post original.

Serapis

#3
En lo primero quería decir que no eras específico y resultaba ambiguo saber si no eras capaz de hacer que tus pruebas hicieran lo que quieres o que daban error en alguna parte y no lograbas encontrar dónde. Es lo que diferencia errores semánticos de errores sintácticos...

Si las 2 primeras pruebas las cumples correctamente, pasamos a las siguientes.., esencialmente son lo mismo con una simple connotación, pero si sabes librar una de ellas, la misma solución (salvo grave omisión, alivia también la siguiente)...

Resistencia a la contribución de bits: Se asocia a un 'ataque de extensión por longitud'  y que pretende evitar que H(mensaje), donde no se conoce el mensaje pero si su longitud, podría dar lugar a que H(mensaje) + mensaje2 dé resultados para un hash del mensaje2, sin siquiera conocer el mensaje1 (mensaje).
Una forma simple de resumirlo es que, la diferenciación entre los hashes de mensajes, no sea proporcional a la longitud de los mismos... más aclaratorio, supongamos un mensaje dado desconocido, si se reconstruye el estado de la función hash a la salida y se añade, una supuesta información extra al mensaje desconocido, ¿puede proporcionar un hash válido para el mismo mensaje + el contenido añadido sin conocer la key usada?. No es un fallo en sí de la función hash, si no una estrategia bien pensada para lograr que la función arroje un hash deseado.

Un modo simple de evitar esto, es utilizar en un estadio temprano (no al final, para que no sea retirada dicha info), la longitud del mensaje como parte del mismo mensaje, así el nuevo cálculo del mensaje al ser variado en su longitud, viene variado a su vez desde el comienzo (en base a las dos condiciones previas de 'preimagen')...

Un ejemplo ficticio, para propósitos aclaratorios (ficticio, en el sentido de que sólo es simbólico).
    H("hola, Buenos días...") = "EF6A9B"
Si quiero que el hash fuere otro conocido y precalculado, pongamos "D56BC12"
podría obtenerse en la forma?:
    H("hola, Buenos días..." + loquesea) =  "D56BC12"

Ese 'loquesea', no es cualquier cosa al azar, sino algo bien meditado, la longitud se precisa conocer, porque habitualmente una función hash opera en 'paquetes' de tamaño dado, y suele ser preciso un padding para completar bloques.

Esto: H("hola, Buenos días..." + loquesea) =  "D56BC12" puede funcionar con algunas funciones, desde el momento en que H("hola, Buenos días..."= "EF6A9B", sabemos que lo genera ya la función luego la parte atacante debe considerar si el saliente + loquesea) puede lograr que sea =  "D56BC12".
Ya te digo que una forma muy simple de evitarlo es considerar el tamaño del mensaje como parte del propio mensaje, esto hará que si inicialmente era:
    H("hola, Buenos días...") = "EF6A9B"
ahora con la longitud podría ser (concedamos que por comodidad fuere el mismo hash resultante que el previo):
    H("hola,020 Buenos días...") = "EF6A9B"
entonces ahora:
    H("hola,020 Buenos días..." + loquesea) ya no podrá dar =  "D56BC12"
porque como el mensaje original se desconoce, al añadir loquesea (supongamos que 'loquesea' fuera exactamente ese mismo texto), se computaría como:
    H("hola,028 Buenos días..." + "loquesea") =  "35B88A"
Nota ahora la longitud '028',  como parte del mensaje original que haría que ahora a la salida de (una etapa que acaba en):
    H("hola,028 Buenos días..." ya no generará lo mismo que  H("hola,020 Buenos días..." que es lo que el atacante esperaría...

Algo más sofisticado, sería no considerar la longitud en el propio mensaje pero sí considerar operar con variación en función de la longitud del mensaje... es decir que no opere secuencialmente del modo que siempre se tenga el mismo hash si el contendo previo es el mismo:
    H("h") = ???
    H("ho") = lo previo + considerar lo nuevo que es "o"
    H("hol") = lo previo + considerar lo nuevo que es "l"
    H("hola") = lo previo + considerar lo nuevo que es "a"
    ...
    H("hola, Buenos dí"  = lo previo + considerar lo nuevo que es "í"
(esto es válido también para el 4º caso, resistencia a la resta de bits, ya que es básicamente lo mismo...)

Considera que si el hash, empezara operando por ejemplo desde la mitad del contenido y al término continuar con el comienzo del contenido...
    H("os días...hola, Buen") = "EF6A9B"
Cualquier añadido (al final o al comienzo), variaría el hash, porque no es depeendiente de una alineación izquierda en el cálculo.
    H("ías...loqueseahola, Buenos d" ) =  "4465B0"
Otra forma es en vez de partir por el medio, considerar el módulo de un primo basado en el tamaño del mensaje...
así para el mensaje original: x = (20 modulo 17) = 3
y para el nuevo mensaje: x = (28 modulo 17) = 11
Todavía podría calcularse un 'loquesea' para que tuviere en cuenta esto mismo, por lo que procede mejor duplicalro, primero en cantidad de paquetes y luego el resto de un paquete....
    x = (((size(mensaje) modulo 17) * 7) +  (size(mensaje) modulo 7))
Como hab´ra mensajes largos y mensajes cortos, sería incluso mejor considerar otro idéntico para cada tipo de mensaje.
    y = (((size(mensaje) modulo 11113) * 251) +  (size(mensaje) modulo 251))
y luego unificarlos:
    z = (x modulo 11) * 29) + (y modulo 29))

Luego z sería en punto del mensaje donde empezar a calcular el hash. Cualquier manipulación añadiendo contenido al mensaje original o sustrayéndolo cambiará ese punto y por tanto el hash resultante... con lo que queda imposible forzar a que se compute un hash específico, a base añadir contenido...

Espero que el tocho aclaratorio sea suficiente para que entiendas el caso... el problema básico a que refiere es la correlación directa de un contenido sobre un contenido + un añadido y la forma más sencilla de evitarlo o una más sofisticada (pero todavía fácil).
Si tu función dispone de varias fases distintas, provee un orden distinto según el tamaño de origen...  eso limita bastante más, posibles colisiones forzadas, buscadas a partir de añadir contenido.

La solución HMAC, no me convence particularmente...
     HMAC = H(key, H(key, contenido))
Preferiría más bien:
     HMAC = H(key, (contenido + H(key, contenido))
pero claro, esto es más costoso en tiempo. Además tampoco me termina de agradar que el hash quede concatenado siempre al final del contenido...

Si te queda alguna duda, avisa...



modificado, para añadirle vistosidad con negritas e identación y no resulte tan tocho...

Alvarito050506

 :o

Muchísimas gracias, lo leí rápidamente, ya lo analizaré y te diré si algo no entiendo (seguramente), pero a simple vista creo que me será extremadamente útil.

;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-)