Due stringhe diverse possono generare lo stesso codice hash MD5?


93

Per ciascuna delle nostre risorse binarie generiamo un hash MD5. Viene utilizzato per verificare se un determinato asset binario è già nella nostra applicazione. Ma è possibile che due diversi asset binari generino lo stesso hash MD5. Quindi è possibile che due stringhe diverse generino lo stesso hash MD5?

Risposte:


93

Anche per un insieme di miliardi di asset, le possibilità di collisioni casuali sono trascurabilmente ridotte , nulla di cui preoccuparsi. Considerando il paradosso del compleanno , dato un set di 2 ^ 64 (o 18.446.744.073.709.551.616) asset, la probabilità di una singola collisione MD5 all'interno di questo set è del 50%. A questa scala, probabilmente batteresti Google in termini di capacità di archiviazione.

Tuttavia, poiché la funzione hash MD5 è stata interrotta (è vulnerabile a un attacco di collisione ), qualsiasi aggressore determinato può produrre 2 risorse in collisione in pochi secondi di potenza della CPU. Quindi, se vuoi usare MD5, assicurati che un tale aggressore non comprometta la sicurezza della tua applicazione!

Inoltre, considera le conseguenze se un utente malintenzionato potesse creare una collisione con una risorsa esistente nel database. Sebbene non siano noti attacchi di questo tipo (attacchi preimage ) contro MD5 (a partire dal 2011), potrebbe diventare possibile estendendo l'attuale ricerca sugli attacchi di collisione.

Se questi risultano essere un problema, suggerisco di guardare la serie SHA-2 di funzioni hash (SHA-256, SHA-384 e SHA-512). Lo svantaggio è che è leggermente più lento e ha una produzione di hash più lunga.


4
"Days" è un'enorme esagerazione a questo punto, a quanto ho capito.
Nick Johnson

1
È vero, ho aggiornato il mio post. L'attacco di collisione casuale del 2004 è davvero molto veloce. L' attacco di collisione con prefisso MD5 del 2007 può richiedere giorni, ma generalmente è molto più utile per un attaccante
intgr

2
Vedi la risposta di Rubens per un esempio funzionante che genererà una collisione tra due diversi eseguibili nel giro di poche ore. :)
Nick Johnson

38

MD5 è una funzione hash, quindi sì, due stringhe diverse possono assolutamente generare codici MD5 in conflitto.

In particolare, si noti che i codici MD5 hanno una lunghezza fissa, quindi il numero possibile di codici MD5 è limitato. Il numero di stringhe (di qualsiasi lunghezza), tuttavia, è decisamente illimitato, quindi ne consegue logicamente che devono esserci collisioni.


12

Sì, è possibile. Questo è in effetti un problema di compleanno . Tuttavia, la probabilità che due stringhe scelte a caso abbiano lo stesso hash MD5 è molto bassa.

Vedi questa e questa domande per esempi.


1
Quale probabilità? Quello della collisione? No, sarebbe 1, cioè molto alto. ;-)
Konrad Rudolph

Ebbene, vero. Esistono sicuramente due stringhe con lo stesso hash MD5.
punta di diamante il

3
L'ho conosciuto come il problema della tana.
Daniel A. White

il problema del compleanno riguarda solo la probabilità di una collisione. per prova ci deve essere uno che vuoi il principio del buco del piccione
jk.

Voterei la tua risposta due volte se potessi. Quanto stiamo parlando di "bassa" probabilità?
Alex Spencer

10

Sì, certo: gli hash MD5 hanno una lunghezza finita, ma ci sono un numero infinito di possibili stringhe di caratteri che possono essere hash MD5.


9

Sì, è possibile che due stringhe diverse possano generare lo stesso codice hash MD5.

Ecco un semplice test che utilizza un messaggio binario molto simile in una stringa esadecimale:

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

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

Generano una somma SHA-1 diversa, ma lo stesso valore hash MD5. In secondo luogo le stringhe sono molto simili, quindi è difficile trovare la differenza tra loro.

La differenza può essere trovata dal seguente 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

L'esempio di collisione sopra è tratto da Marc Stevens: Collisione blocco singolo per MD5 , 2012; spiega il suo metodo, con codice sorgente ( link alternativo al paper ).


Un altro test:

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

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

Somma SHA-1 diversa, stesso hash MD5.

La differenza è in 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

L'esempio sopra è adattato da Tao Xie e Dengguo Feng: Construct MD5 Collisions Using Just A Single Block Of Message , 2010.


Relazionato:


4

Sì, è possibile. Si chiama collisione hash .

Detto questo, algoritmi come MD5 sono progettati per ridurre al minimo la probabilità di una collisione.

La voce di Wikipedia su MD5 spiega alcune vulnerabilità in MD5, di cui dovresti essere a conoscenza.


4

Solo per essere più informativo. Da un punto di vista matematico, le funzioni hash non sono iniettive .
Significa che non esiste una relazione 1 a 1 (ma unidirezionale) tra il set di partenza e quello risultante.

Biiezione su wikipedia

EDIT: per essere completi esistono funzioni hash iniettive: si chiama Perfect hashing .


1
Non esiste una funzione di hashing perfetta quando la dimensione dell'output è inferiore alla dimensione dell'input.
Paŭlo Ebermann

3

Sì! La collisione sarà una possibilità (anche se il rischio è molto basso). In caso contrario, avresti un metodo di compressione piuttosto efficace!

EDIT : come dice Konrad Rudolph: un insieme potenzialmente illimitato di input convertito in un insieme finito di output (32 caratteri esadecimali) si tradurrà in un numero infinito di collisioni.


3

Come altre persone hanno detto, sì, possono esserci collisioni tra due diversi input. Tuttavia, nel tuo caso d'uso, non vedo che sia un problema. Dubito fortemente che incorrerai in collisioni: ho usato MD5 per il fingerprinting di centinaia di migliaia di file immagine di diversi formati di immagine (JPG, bitmap, PNG, raw) in un lavoro precedente e non ho avuto una collisione .

Tuttavia, se stai tentando di imprimere un qualche tipo di dati, forse potresti usare due algoritmi hash: le probabilità di un input che risulti nello stesso output di due algoritmi diversi sono quasi impossibili.


1
In realtà, se un attaccante può produrre collisioni con un algoritmo hash, può usarlo per ottenere collisioni anche per un secondo algoritmo. Questo è stato discusso di recente sulla mia domanda su crypto.stackexchange .
Paŭlo Ebermann

2

Mi rendo conto che questo è vecchio, ma ho pensato di contribuire con la mia soluzione. Ci sono 2 ^ 128 possibili combinazioni di hash. E quindi una probabilità 2 ^ 64 di un paradosso del compleanno. Sebbene la soluzione di seguito non eliminerà la possibilità di collisioni, ridurrà sicuramente il rischio di una quantità molto sostanziale.

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

Quello che ho fatto è mettere insieme alcuni hash in base alla stringa di input per ottenere una stringa risultante molto più lunga che consideri il tuo hash ...

Quindi il mio pseudo-codice per questo è:

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

Cioè all'improbabilità pratica di una collisione. Ma se vuoi essere super paranoico e non puoi farlo accadere, e lo spazio di archiviazione non è un problema (né i cicli di elaborazione) ...

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

Ok, non è la soluzione più pulita, ma questo ora ti fa giocare molto di più con la frequenza con cui incapperai in una collisione. Al punto potrei presumere l'impossibilità in tutti i sensi realistici del termine.

Per amor mio, penso che la possibilità di una collisione sia abbastanza rara da considerarla non "sicura", ma così improbabile che si adatti alle necessità.

Ora le possibili combinazioni aumentano notevolmente. Anche se potresti dedicare molto tempo a quante combinazioni questo potrebbe ottenere, dirò in teoria che ti atterra SIGNIFICATIVAMENTE più del numero citato sopra di

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

Probabilmente di un centinaio di cifre in più. Il massimo teorico che questo potrebbe darti sarebbe

Possibile numero di stringhe risultanti:

528294531135665246352339784916516606518847326036121522127960709026673902556724859474417255887657187894674394993257128678882347559502685537250538978462939576908386683999005084168731517676426441053024232908211188404148028292751561738838396898767036476489538580897737998336


1

Penso che dobbiamo stare attenti a scegliere l'algoritmo di hashing secondo i nostri requisiti, poiché le collisioni di hash non sono così rare come mi aspettavo. Recentemente ho trovato un caso molto semplice di collisione di hash nel mio progetto. Sto usando il wrapper Python di xxhash per l'hashing. Collegamento: https://github.com/ewencp/pyhashxx

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

Ha causato un problema di memorizzazione nella cache molto complicato nel sistema, quindi ho finalmente scoperto che si tratta di una collisione di hash.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.