¿Pueden dos cadenas diferentes generar el mismo código hash MD5?

93

Para cada uno de nuestros activos binarios generamos un hash MD5. Esto se usa para verificar si un determinado activo binario ya está en nuestra aplicación. Pero, ¿es posible que dos activos binarios diferentes generen el mismo hash MD5? Entonces, ¿es posible que dos cadenas diferentes generen el mismo hash MD5?

Lieven Cardoen
fuente

Respuestas:

93

Para un conjunto de incluso miles de millones de activos, las posibilidades de colisiones aleatorias son insignificantes , nada de lo que deba preocuparse. Considerando la paradoja del cumpleaños , dado un conjunto de 2 ^ 64 (o 18,446,744,073,709,551,616) activos, la probabilidad de una sola colisión MD5 dentro de este conjunto es del 50%. A esta escala, probablemente superaría a Google en términos de capacidad de almacenamiento.

Sin embargo, debido a que la función hash MD5 se ha roto (es vulnerable a un ataque de colisión ), cualquier atacante determinado puede producir 2 activos en colisión en cuestión de segundos de potencia de CPU. Por lo tanto, si desea utilizar MD5, asegúrese de que un atacante de este tipo no comprometa la seguridad de su aplicación.

Además, considere las ramificaciones si un atacante pudiera forjar una colisión con un activo existente en su base de datos. Si bien no existen tales ataques conocidos (ataques de preimagen ) contra MD5 (a partir de 2011), podría ser posible ampliando la investigación actual sobre ataques de colisión.

Si estos resultan ser un problema, sugiero mirar la serie SHA-2 de funciones hash (SHA-256, SHA-384 y SHA-512). La desventaja es que es un poco más lento y tiene una salida de hash más larga.

intgr
fuente
4
'Días' es una exageración enorme en este punto, según tengo entendido.
Nick Johnson
1
Es cierto que actualicé mi publicación. El ataque de colisión aleatoria de 2004 es realmente muy rápido. El ataque de colisión de prefijo MD5 de 2007 puede tardar días, pero generalmente es mucho más útil para un atacante
intgr
2
Consulte la respuesta de Rubens para ver un ejemplo funcional que generará una colisión entre dos ejecutables diferentes en cuestión de horas. :)
Nick Johnson
38

MD5 es una función hash , así que sí, dos cadenas diferentes pueden generar absolutamente códigos MD5 en colisión.

En particular, tenga en cuenta que los códigos MD5 tienen una longitud fija, por lo que el número posible de códigos MD5 es limitado. Sin embargo, el número de cadenas (de cualquier longitud) es definitivamente ilimitado, por lo que lógicamente se deduce que debe haber colisiones.

Konrad Rudolph
fuente
12

Sí, es posible. De hecho, este es un problema de cumpleaños . Sin embargo, la probabilidad de que dos cadenas elegidas al azar tengan el mismo hash MD5 es muy baja.

Vea esta y esta pregunta para ver ejemplos.

diente filoso
fuente
1
¿Qué probabilidad? ¿El de la colisión? No, eso sería 1, es decir, muy alto. ;-)
Konrad Rudolph
Bueno, es cierto. Seguramente existen dos cadenas con el mismo hash MD5.
diente afilado
3
He conocido esto como el problema del casillero.
Daniel A. White
el problema del cumpleaños solo se refiere a la probabilidad de una colisión. como prueba, debe haber uno que desee el principio del agujero de pidgeon
jk.
Votaría su respuesta dos veces si pudiera. ¿Qué tan "baja" de probabilidad estamos hablando?
Alex Spencer
10

Sí, por supuesto: los hash MD5 tienen una longitud finita, pero hay un número infinito de cadenas de caracteres posibles que pueden tener hash MD5.

Tony Andrews
fuente
9

Sí, es posible que dos cadenas diferentes puedan generar el mismo código hash MD5.

Aquí hay una prueba simple que usa un mensaje binario muy similar en una cadena hexadecimal:

$ echo '4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa200a8284bf36e8e4b55b35f427593d849676da0d1555d8360fb5f07fea2' | xxd -r -p | tee >/dev/null >(md5) >(sha1sum)
c6b384c4968b28812b676b49d40c09f8af4ed4cc  -
008ee33a9d58b51cfeb425b0959121c9

$ echo '4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa202a8284bf36e8e4b55b35f427593d849676da0d1d55d8360fb5f07fea2' | xxd -r -p | tee >/dev/null >(md5) >(sha1sum)
c728d8d93091e9c7b87b43d9e33829379231d7ca  -
008ee33a9d58b51cfeb425b0959121c9

Generan una suma SHA-1 diferente, pero el mismo valor hash MD5. En segundo lugar, las cadenas son muy similares, por lo que es difícil encontrar la diferencia entre ellas.

La diferencia se puede encontrar con el siguiente comando:

$ diff -u <(echo 4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa200a8284bf36e8e4b55b35f427593d849676da0d1555d8360fb5f07fea2 | fold -w2) <(echo 4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa202a8284bf36e8e4b55b35f427593d849676da0d1d55d8360fb5f07fea2 | fold -w2)
--- /dev/fd/63  2016-02-05 12:55:04.000000000 +0000
+++ /dev/fd/62  2016-02-05 12:55:04.000000000 +0000
@@ -33,7 +33,7 @@
 af
 bf
 a2
-00
+02
 a8
 28
 4b
@@ -53,7 +53,7 @@
 6d
 a0
 d1
-55
+d5
 5d
 83
 60

El ejemplo de colisión anterior está tomado de Marc Stevens: Colisión de bloque único para MD5 , 2012; explica su método, con código fuente ( enlace alternativo al artículo ).


Otra prueba:

$ echo '0e306561559aa787d00bc6f70bbdfe3404cf03659e704f8534c00ffb659c4c8740cc942feb2da115a3f4155cbb8607497386656d7d1f34a42059d78f5a8dd1ef' | xxd -r -p | tee >/dev/null >(md5) >(sha1sum)
756f3044edf52611a51a8fa7ec8f95e273f21f82  -
cee9a457e790cf20d4bdaa6d69f01e41

$ echo '0e306561559aa787d00bc6f70bbdfe3404cf03659e744f8534c00ffb659c4c8740cc942feb2da115a3f415dcbb8607497386656d7d1f34a42059d78f5a8dd1ef' | xxd -r -p | tee >/dev/null >(md5) >(sha1sum)
6d5294e385f50c12745a4d901285ddbffd3842cb  -
cee9a457e790cf20d4bdaa6d69f01e41

Diferente suma SHA-1, el mismo hash MD5.

La diferencia está en un byte:

$ diff -u <(echo 0e306561559aa787d00bc6f70bbdfe3404cf03659e704f8534c00ffb659c4c8740cc942feb2da115a3f4155cbb8607497386656d7d1f34a42059d78f5a8dd1ef | fold -w2) <(echo 0e306561559aa787d00bc6f70bbdfe3404cf03659e744f8534c00ffb659c4c8740cc942feb2da115a3f415dcbb8607497386656d7d1f34a42059d78f5a8dd1ef | fold -w2)
--- /dev/fd/63  2016-02-05 12:56:43.000000000 +0000
+++ /dev/fd/62  2016-02-05 12:56:43.000000000 +0000
@@ -19,7 +19,7 @@
 03
 65
 9e
-70
+74
 4f
 85
 34
@@ -41,7 +41,7 @@
 a3
 f4
 15
-5c
+dc
 bb
 86
 07

El ejemplo anterior está adaptado de Tao Xie y Dengguo Feng: Construct MD5 Collisions Using Just A Single Block Of Message , 2010.


Relacionado:

Kenorb
fuente
4

Sí, es posible. Se llama colisión Hash .

Dicho esto, los algoritmos como MD5 están diseñados para minimizar la probabilidad de una colisión.

La entrada de Wikipedia en MD5 explica algunas vulnerabilidades en MD5, que debe conocer.

Wernsey
fuente
4

Solo para ser más informativo. Desde un punto de vista matemático, las funciones hash no son inyectivas .
Significa que no hay una relación 1 a 1 (sino unidireccional) entre el conjunto inicial y el resultante.

Bijection en wikipedia

EDITAR: para ser completo existen funciones hash inyectivas: se llama hash perfecto .

Roubachof
fuente
1
No existe una función hash perfecta cuando el tamaño de salida es menor que el tamaño de entrada.
Paŭlo Ebermann
3

¡Sí lo es! La colisión será una posibilidad (aunque el riesgo es muy pequeño). Si no, ¡tendría un método de compresión bastante efectivo!

EDITAR : Como dice Konrad Rudolph: Un conjunto de entrada potencialmente ilimitado convertido en un conjunto finito de salida (32 caracteres hexadecimales) dará como resultado un número infinito de colisiones.

jensgram
fuente
3

Como han dicho otras personas, sí, puede haber colisiones entre dos entradas diferentes. Sin embargo, en su caso de uso, no veo que eso sea un problema. Dudo mucho que se encuentre con colisiones: he usado MD5 para tomar huellas digitales de cientos de miles de archivos de imagen de varios formatos de imagen (JPG, mapa de bits, PNG, sin formato) en un trabajo anterior y no tuve una colisión .

Sin embargo, si está tratando de tomar huellas dactilares de algún tipo de datos, tal vez podría usar dos algoritmos hash; las probabilidades de que una entrada dé como resultado la misma salida de dos algoritmos diferentes es casi imposible.

Thomas Owens
fuente
1
En realidad, si un atacante puede producir colisiones con un algoritmo hash, puede usarlo para obtener también colisiones para un segundo algoritmo. Esto se discutió recientemente sobre mi pregunta en crypto.stackexchange .
Paŭlo Ebermann
2

Me doy cuenta de que esto es antiguo, pero pensé en contribuir con mi solución. Hay 2 ^ 128 posibles combinaciones de hash. Y así una probabilidad de 2 ^ 64 de una paradoja de cumpleaños. Si bien la solución a continuación no eliminará la posibilidad de colisiones, seguramente reducirá el riesgo en una cantidad muy sustancial.

2^64 = 18,446,744,073,709,500,000 possible combinations

Lo que he hecho es juntar algunos hash en función de la cadena de entrada para obtener una cadena resultante mucho más larga que considere su hash ...

Entonces mi pseudocódigo para esto es:

Result = Hash(string) & Hash(Reverse(string)) & Hash(Length(string))

Eso es prácticamente improbabilidad de una colisión. Pero si quieres ser súper paranoico y no puedes permitir que suceda, y el espacio de almacenamiento no es un problema (ni los ciclos de computación) ...

Result = Hash(string) & Hash(Reverse(string)) & Hash(Length(string)) 
         & Hash(Reverse(SpellOutLengthWithWords(Length(string)))) 
         & Hash(Rotate13(string)) Hash(Hash(string)) & Hash(Reverse(Hash(string)))

De acuerdo, no es la solución más limpia, pero esto ahora le permite jugar mucho más con la poca frecuencia con la que se encontrará con una colisión. Hasta el punto que podría asumir la imposibilidad en todos los sentidos realistas del término.

Por mi bien, creo que la posibilidad de una colisión es lo suficientemente poco frecuente como para considerar que esto no es "seguro", pero es tan poco probable que suceda que se adapte a la necesidad.

Ahora las combinaciones posibles aumentan significativamente. Si bien podría dedicar mucho tiempo a la cantidad de combinaciones que esto podría obtener, diré que, en teoría, lo llevará SIGNIFICATIVAMENTE más que el número citado anteriormente de

2^64 (or 18,446,744,073,709,551,616) 

Probablemente unos cien dígitos más. El máximo teórico que esto podría darte sería

Posible número de cadenas resultantes:

528294531135665246352339784916516606518847326036121522127960709026673902556724859474417255887657187894674394993257128678882347559502685537250538978462939576908386683999005084168731517676426441053024232908211188404148028292751561738838396898767036476489538580897737998336

Andrés
fuente
1

Creo que debemos tener cuidado al elegir el algoritmo hash según nuestro requisito, ya que las colisiones hash no son tan raras como esperaba. Recientemente encontré un caso muy simple de colisión de hash en mi proyecto. Estoy usando la envoltura de Python de xxhash para hacer hash. Enlace: https://github.com/ewencp/pyhashxx

s1 = 'mdsAnalysisResult105588'
s2 = 'mdsAlertCompleteResult360224'
pyhashxx.hashxx(s1) # Out: 2535747266
pyhashxx.hashxx(s2) # Out: 2535747266

Causó un problema de almacenamiento en caché muy complicado en el sistema, luego finalmente descubrí que es una colisión de hash.

i_am_saurabh
fuente