Come mai i valori hash MD5 non sono reversibili?


91

Un concetto su cui mi sono sempre chiesto è l'uso di funzioni e valori hash crittografici. Capisco che queste funzioni possano generare un valore hash che è unico e praticamente impossibile da invertire, ma ecco cosa mi sono sempre chiesto:

Se sul mio server, in PHP produco:

md5("stackoverflow.com") = "d0cc85b26f2ceb8714b978e07def4f6e"

Quando esegui la stessa stringa tramite una funzione MD5, ottieni lo stesso risultato sulla tua installazione PHP. Viene utilizzato un processo per produrre un valore, da un valore iniziale.

Questo non significa che c'è un modo per decostruire ciò che sta accadendo e invertire il valore hash?

Di cosa si tratta in queste funzioni che rende impossibile rintracciare le stringhe risultanti?


54
Un semplice esempio di valore non reversibile, ad esempio, è modulo. Ad esempio 10% 3 = 1, ma non puoi invertire l'1 in 10 poiché potrebbe anche essere 4
Gab Royer

57
Se potessi ricostruire i dati avresti l'algoritmo di compressione lossless più efficiente di sempre :)
Dan Diplo

Risposte:


204

Il materiale in ingresso può avere una lunghezza infinita, in cui l'uscita è sempre di 128 bit. Ciò significa che un numero infinito di stringhe di input genererà lo stesso output.

Se scegli un numero casuale e lo dividi per 2 ma scrivi solo il resto, otterrai uno 0 o 1, rispettivamente pari o dispari. È possibile prendere quello 0 o 1 e ottenere il numero originale?


4
Vale a dire, né numero -> resto né stringa -> md5 sono "funzioni iniettive".
Federico A. Ramponi

Federico, sicuramente vuoi dire che nemmeno le funzioni biiettive? Sono entrambi iniettivi.
Mihai Limbășan

10
moocha: Injective significa 1 a 1. L'MD5 non è certamente 1 a 1, poiché il dominio è più grande dell'intervallo. Un altro punto degno di nota è che, dato un checksum MD5, è molto difficile trovare anche una sola stringa con l'hash. Potrebbe valere la pena aggiungere alla risposta per chiarimenti.
biozinc

4
È impossibile avere una funzione hash che generi valori univoci. Stai mappando un numero infinito di valori in un numero finito di valori, il che garantisce le collisioni.
Cody Brocious,

4
Suggerirei che la tua risposta non affronti il ​​punto chiave. Come menzionato da biozinc, ciò che è importante per un hash della password sicuro è che non riesci a trovare alcun input che crea l'output, non che non riesci a trovare l'input originale. In questa nota, MD5 non è necessariamente sicuro come potrebbe essere ( en.wikipedia.org/wiki/MD5#Collision_vulnerabilities ).
Mike Pelley

53

Se le funzioni hash come MD5 fossero reversibili, sarebbe stato un evento spartiacque nella storia degli algoritmi di compressione dei dati! È facile vedere che se MD5 fosse reversibile, blocchi arbitrari di dati di dimensioni arbitrarie potrebbero essere rappresentati da soli 128 bit senza alcuna perdita di informazioni. In questo modo saresti stato in grado di ricostruire il messaggio originale da un numero di 128 bit indipendentemente dalla dimensione del messaggio originale.


9
pensa quanto sarebbe veloce scaricare le distribuzioni Linux se potessi ottenere invece l'md5 :)
Colin Pickard

15
@Colin Pickard: non avremmo più scaricato le distribuzioni Linux, le avremmo annotate . :)
tzot

29

Contrariamente a quanto sottolineano le risposte più votate qui, la non iniettività (cioè che ci sono più stringhe che hanno lo stesso valore) di una funzione hash crittografica causata dalla differenza tra la dimensione di input grande (potenzialmente infinita) e la dimensione di output fissa non lo è il punto importante - in realtà, preferiamo le funzioni hash in cui tali collisioni avvengono il più raramente possibile.

Considera questa funzione (nella notazione PHP, come domanda):

function simple_hash($input) {
     return bin2hex(substr(str_pad($input, 16), 0, 16));
}

Questo aggiunge alcuni spazi, se la stringa è troppo corta, quindi prende i primi 16 byte della stringa, quindi la codifica come esadecimale. Ha la stessa dimensione di output di un hash MD5 (32 caratteri esadecimali o 16 byte se omettiamo la parte bin2hex).

print simple_hash("stackoverflow.com");

Questo produrrà:

737461636b6f766572666c6f772e636f6d

Questa funzione ha anche la stessa proprietà di non iniettività evidenziata dalla risposta di Cody per MD5: possiamo passare stringhe di qualsiasi dimensione (purché si adattino al nostro computer) e produrrà solo 32 cifre esadecimali. Ovviamente non può essere iniettivo.

Ma in questo caso, è banale trovare una stringa che mappa lo stesso hash (basta applicarlo hex2binsul tuo hash e il gioco è fatto). Se la tua stringa originale aveva la lunghezza 16 (come il nostro esempio), otterrai anche questa stringa originale. Niente di questo tipo dovrebbe essere possibile per MD5, anche se sai che la lunghezza dell'input è piuttosto breve (a parte provare tutti gli input possibili finché non ne troviamo uno che corrisponda, ad esempio un attacco di forza bruta).

I presupposti importanti per una funzione hash crittografica sono:

  • è difficile trovare una stringa che produca un dato hash (resistenza preimage)
  • è difficile trovare una stringa diversa che produca lo stesso hash di una determinata stringa (seconda resistenza preimage)
  • è difficile trovare qualsiasi coppia di stringhe con lo stesso hash (resistenza alle collisioni)

Ovviamente la mia simple_hashfunzione non soddisfa nessuna di queste condizioni. (In realtà, se restringiamo lo spazio di input a "stringhe di 16 byte", la mia funzione diventa iniettiva, e quindi è anche dimostrabile che resiste alla seconda immagine e alle collisioni.)

Ora esistono attacchi di collisione contro MD5 (ad esempio è possibile produrre una coppia di stringhe, anche con un dato stesso prefisso, che hanno lo stesso hash, con un bel po 'di lavoro, ma non impossibile molto lavoro), quindi non dovresti usare MD5 per qualsiasi cosa critica. Non è ancora disponibile un attacco preimmagine, ma gli attacchi miglioreranno.

Per rispondere alla domanda effettiva:

Di cosa si tratta in queste funzioni che rende impossibile rintracciare le stringhe risultanti?

Ciò che MD5 (e altre funzioni hash si basano sulla costruzione Merkle-Damgard) effettivamente fanno è applicare un algoritmo di crittografia con il messaggio come chiave e un valore fisso come "testo normale", utilizzando il testo cifrato risultante come hash. (Prima di ciò, l'input viene riempito e suddiviso in blocchi, ciascuno di questi blocchi viene utilizzato per crittografare l'output del blocco precedente, XORed con il suo input per evitare calcoli inversi.)

I moderni algoritmi di crittografia (inclusi quelli utilizzati nelle funzioni hash) sono realizzati in modo da rendere difficile il recupero della chiave, anche con testo in chiaro e cifrato (o anche quando l'avversario ne sceglie uno). Lo fanno generalmente eseguendo molte operazioni di mescolamento dei bit in modo che ogni bit di uscita sia determinato da ogni bit chiave (più volte) e anche da ogni bit di ingresso. In questo modo puoi rintracciare facilmente cosa succede all'interno se conosci la chiave completa e l'input o l'output.

Per le funzioni hash tipo MD5 e un attacco preimage (con una stringa hash a blocco singolo, per semplificare le cose), hai solo input e output della tua funzione di crittografia, ma non la chiave (questo è quello che stai cercando).


4
Sì, lo so che questa è una risposta abbastanza tardiva, ma la risposta accettata non dovrebbe essere lasciata in questo modo.
Paŭlo Ebermann

Penso che le tue critiche abbiano qualche merito ma non sei riuscito a rispondere alla domanda vera e propria "Cosa c'è in queste funzioni che rende impossibile rintracciare le stringhe risultanti?" La tua risposta si concentra sulle qualità che un hash crittografico dovrebbe avere ma non ha alcuna spiegazione su come vengono implementati da md5. Potresti indicare qui l'algoritmo esatto per calcolare le somme MD5 per mostrare come non sia reversibile, ma le altre risposte forniscono una spiegazione più semplice senza entrare nei dettagli.
Autodidatta

(cont ...) 2. Queste spiegazioni usano "Math" per mostrare un problema fondamentale per il quale tali operazioni perdono informazioni e diventano irreversibili.
Autodidatta

1
@SandeepDatta Ho aggiunto alcuni paragrafi su questo.
Paŭlo Ebermann

1
Mentre altre risposte in questo thread sono tecnicamente più corrette, questa risposta è la più utile. La funzione non iniettiva f (x) = 1 non è reversibile ma non è interessante. L'utilità dell'hashing risiede nella resistenza pre-immagine in cui è difficile trovare qualsiasi input che produca un output specifico.
Justin J Stark

18

La risposta di Cody Brocious è quella giusta. A rigor di termini, non è possibile "invertire" una funzione hash perché molte stringhe sono mappate sullo stesso hash. Si noti, tuttavia, che trovare una stringa che viene mappata su un dato hash o trovare due stringhe che vengono mappate sullo stesso hash (cioè una collisione ), sarebbero importanti scoperte per un crittoanalista. La grande difficoltà di entrambi questi problemi è la ragione per cui buone funzioni hash sono utili nella crittografia.


12

MD5 non crea un valore hash univoco; l'obiettivo di MD5 è quello di produrre rapidamente un valore che cambia in modo significativo in base a una piccola modifica alla sorgente.

Per esempio,

"hello" -> "1ab53"
"Hello" -> "993LB"
"ZR#!RELSIEKF" -> "1ab53"

(Ovviamente non è la vera crittografia MD5)

Anche la maggior parte degli hash (se non tutti) non sono univoci; piuttosto, sono abbastanza unici , quindi una collisione è altamente improbabile, ma comunque possibile.


8

Un buon modo per pensare a un algoritmo hash è pensare di ridimensionare un'immagine in Photoshop ... supponiamo di avere un'immagine di 5000x5000 pixel e poi ridimensionarla a soli 32x32. Quello che hai è ancora una rappresentazione dell'immagine originale, ma è molto molto più piccola e ha effettivamente "buttato via" alcune parti dei dati dell'immagine per adattarla alle dimensioni più piccole. Quindi, se dovessi ridimensionare l'immagine 32x32 fino a 5000x5000, tutto ciò che otterresti sarebbe un pasticcio sfocato. Tuttavia, poiché un'immagine 32x32 non è così grande, sarebbe teoricamente concepibile che un'altra immagine possa essere ridimensionata per produrre esattamente gli stessi pixel!

È solo un'analogia, ma aiuta a capire cosa sta facendo un hash.


3
Sebbene il ridimensionamento dell'immagine sia un processo con perdita di dati, è comunque abbastanza facile produrre un'immagine nella dimensione originale di 5000 × 5000 che (quando si applica nuovamente la funzione di riduzione) si ridurrà alla stessa immagine 32 × 32. Trovare una tale immagine preliminare dovrebbe essere difficile per una buona funzione hash.
Paŭlo Ebermann

4

Una collisione di hash è molto più probabile di quanto pensi. Dai un'occhiata al paradosso del compleanno per capire meglio il motivo.


1
Ci sono 365 possibili valori di compleanno, che è compreso tra 2 ^ 8 e 2 ^ 9. Un hash a 128 bit ha 2 ^ 128 valori possibili - 2 ^ 120 volte di più. Sì, le collisioni sono più probabili di quanto potresti intuire, ma sono ancora astronomicamente improbabili.
Tim Keating

Avrai bisogno di circa 2 ^ 64 valori diversi per avere buone possibilità di una collisione hash. Ancora un bel po '.
Paŭlo Ebermann

4

Poiché il numero di file di input possibili è maggiore del numero di output a 128 bit, è impossibile assegnare in modo univoco un hash MD5 a ciascuno di essi.

Le funzioni hash crittografiche vengono utilizzate per controllare l'integrità dei dati o le firme digitali (l'hash viene firmato per l'efficienza). La modifica del documento originale dovrebbe quindi significare che l'hash originale non corrisponde al documento alterato.

A volte vengono utilizzati questi criteri:

  1. Resistenza all'immagine: per una data funzione hash e un dato hash, dovrebbe essere difficile trovare un input che abbia l'hash dato per quella funzione.
  2. Seconda resistenza prima dell'immagine: per una data funzione hash e input, dovrebbe essere difficile trovare un secondo input, diverso, con lo stesso hash.
  3. Resistenza alle collisioni: per un dato ha una funzione, dovrebbe essere difficile trovare due diversi input con lo stesso hash.

Questi criteri vengono scelti per rendere difficile trovare un documento che corrisponda a un dato hash, altrimenti sarebbe possibile falsificare i documenti sostituendo l'originale con uno che corrisponde all'hash. (Anche se la sostituzione è incomprensibile, la semplice sostituzione dell'originale può causare interruzioni.)

Il numero 3 implica il numero 2.

Per quanto riguarda MD5 in particolare, è stato dimostrato che è difettoso: come rompere MD5 e altre funzioni hash .


2

Ma è qui che entrano in gioco i tavoli arcobaleno. Fondamentalmente è solo una grande quantità di valori hash separatamente e quindi il risultato viene salvato su disco. Quindi il bit di inversione è "solo" per fare una ricerca in una tabella molto grande.

Ovviamente questo è possibile solo per un sottoinsieme di tutti i possibili valori di input, ma se si conoscono i limiti del valore di input potrebbe essere possibile calcolarlo.


Ah sì. Mi è piaciuto leggere il post di Jeff su Hash Tables ( codinghorror.com/blog/archives/000949.html ), e questo thread ha aiutato nella comprensione del concetto.
barfoon


1

Come molti hanno già detto, MD5 è stato progettato per flussi di dati di lunghezza variabile da sottoporre a hashing su un blocco di dati di lunghezza fissa, quindi un singolo hash è condiviso da molti flussi di dati di input.

Tuttavia, se hai mai avuto bisogno di scoprire i dati originali dal checksum, ad esempio se hai l'hash di una password e devi scoprire la password originale, spesso è più veloce solo google (o qualunque ricercatore preferisci) l'hash per la risposta che per forza bruta. Ho scoperto con successo alcune password usando questo metodo.


1

Il modo migliore per capire cosa significassero tutte le risposte più votate è provare effettivamente a ripristinare l'algoritmo MD5. Ricordo di aver provato a ripristinare l' algoritmo MD5crypt alcuni anni fa, non per recuperare il messaggio originale perché è chiaramente impossibile, ma solo per generare un messaggio che avrebbe prodotto lo stesso hash dell'hash originale. Questo, almeno in teoria, mi fornirebbe un modo per accedere a un dispositivo Linux che memorizza l'utente: password nel file / etc / passwd usando il messaggio generato (password) invece di usare quello originale. Poiché entrambi i messaggi avrebbero lo stesso hash risultante, il sistema riconoscerà la mia password (generata dall'hash originale) come valida. Non ha funzionato affatto. Dopo diverse settimane, se non ricordo male, l'uso del salenel messaggio iniziale mi ha ucciso. Ho dovuto produrre non solo un messaggio iniziale valido, ma un messaggio iniziale valido e salato, cosa che non sono mai stato in grado di fare. Ma la conoscenza che ho ottenuto da questo esperimento è stata piacevole.


Se fossi in grado di generare un input che ha prodotto il valore hash MD5 dato in modo ragionevolmente efficiente, sarebbe un grosso problema per la comunità crittografica e dovrebbe essere pubblicato. Questo è completamente indipendente dal fatto che un particolare input sia stato salato.
Dave L.

0

per definizione funzione Hash (hash crittografico): non dovrebbe essere invertibile; non dovrebbe avere collisioni (il meno possibile).

regd la tua domanda: è un modo hash. input (indipendentemente dalla lunghezza) genererà un output di dimensione fissa (verrà riempito in base all'algoritmo (limite di 512 bit per MD5)). Le informazioni vengono compresse (perse) e praticamente non è possibile generarle dalle trasformazioni inverse.

informazioni aggiuntive su MD5: è vulnerabile alle collisioni. ho letto questo articolo di recente, http://www.win.tue.nl/hashclash/Nostradamus/

apre il codice sorgente per le implementazioni di hash crypto (MD5 e SHA) può essere trovato su Mozilla code. (libreria freebl).


0

Ora un giorno gli hash MD5 o qualsiasi altro hash per quella materia vengono pre-calcolati per tutte le stringhe possibili e archiviati per un facile accesso. Sebbene in teoria MD5 non sia reversibile, ma utilizzando tali database è possibile scoprire quale testo ha prodotto un particolare valore hash.

Ad esempio, prova il seguente codice hash su http://gdataonline.com/seekhash.php per scoprire quale testo ho usato per calcolare l'hash

aea23489ce3aa9b6406ebb28e0cda430

Ah, sì, l'hash di una comune parola di 7 lettere. Ora usalo per capire il testo di questa canzone di 11 parole con spazi bianchi e punteggiatura: 9f2c08d4e6158bd4854b15be50c8daa8. Ci vediamo tra diversi millenni.
Tim Keating

6fba2bbab8a8366309bf67c7df12c622? Suggerimento: potrebbe essere la versione OEM di una versione specifica di Mac OS X!
scherand

@Tim Keating, @scherand: Sto solo sottolineando la debolezza degli algoritmi hash, poiché l'hash di una stringa è sempre lo stesso, non abbiamo necessariamente bisogno di crackare l'algoritmo per capire la stringa effettiva.
Babar

2
Ma non è quello che hai detto. Hai detto che gli hash sono "precalcolati per tutte le stringhe possibili e memorizzati per un facile accesso" il che è palesemente falso (l'insieme di "tutte le stringhe possibili "èinfinito ... e anche l'insieme di" tutte le stringhe plausibili "èdavvero, molto grande ). IMHO questo travisa quanto sia facile eseguire un attacco del dizionario contro una passphrase ragionevole.
Tim Keating

0

f (x) = 1 è irreversibile. Le funzioni hash non sono irreversibili.

Questo è effettivamente necessario per svolgere la loro funzione di determinare se qualcuno possiede una copia non danneggiata dei dati sottoposti a hashing. Ciò aumenta la suscettibilità agli attacchi di forza bruta, che sono piuttosto potenti in questi giorni, in particolare contro MD5.

C'è anche confusione qui e altrove tra le persone che hanno conoscenze matematiche ma poca conoscenza di cifratura. Diversi cifrari semplicemente XOR i dati con il keystream, e così potreste dire che un testo cifrato corrisponde a tutti i testi in chiaro di quella lunghezza perché avreste potuto usare qualsiasi keystream.

Tuttavia, questo ignora che un testo in chiaro ragionevole prodotto dal seme passwordè molto, molto più probabile di un altro prodotto dal seme Wsg5Nm^bkI4EgxUOhpAjTmTjO0F!VkWvysS6EEMsIJiTZcvsh@WI$IH$TYqiWvK!%&Ue&nk55ak%BX%9!NnG%32ftud%YkBO$U6onella misura in cui chiunque affermi che la seconda era una possibilità sarebbe deriso.

Allo stesso modo, se stai cercando di decidere tra le due potenziali password passworde Wsg5Nm^bkI4EgxUO, non è così difficile da fare come alcuni matematici vorrebbero farti credere.


Dove prendi i tuoi cifrari Most semplicemente XOR i dati con la conoscenza del keystream ? Questo è vero per i cifrari a flusso, ma ci sono anche cifrari a blocchi e non funzionano in questo modo.
Paŭlo Ebermann

-5

Mi piacciono tutti i vari argomenti. È ovvio che il vero valore dei valori con hash è semplicemente quello di fornire segnaposto illeggibili per stringhe come le password. Non ha alcun vantaggio specifico per la sicurezza avanzata. Supponendo che un utente malintenzionato abbia ottenuto l'accesso a una tabella con password con hash, può:

  • Hash una password di sua scelta e inserire i risultati nella tabella delle password se ha i diritti di scrittura / modifica sulla tabella.
  • Genera valori hash di password comuni e verifica l'esistenza di valori hash simili nella tabella delle password.

In questo caso, le password deboli non possono essere protette dal semplice fatto che sono state sottoposte ad hashing.


Il vero valore dei "valori hash" non è fornire segnaposti illeggibili. Se "password1" è stato trasformato in "newval", non nasconde ancora il valore in modo simile, sebbene l'hash sia leggibile e significativo? Inoltre, le password sono un cattivo esempio, perché non dovrebbero MAI essere sottoposte ad hashing. Supponendo che l'aggressore avesse accesso in scrittura a detto database, questa è sicuramente una possibilità. Tuttavia sembra che tu stia semplicemente scartando l'uso corretto di tali funzioni di hashing, un esempio è delineato nelle molte risposte sopra: integrità del messaggio. In realtà è il motivo per cui oggi sono su questo thread.
Shane
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.