Quale funzione hash crittografica dovrei scegliere?


137

Il framework .NET viene fornito con 6 diversi algoritmi di hashing:

  • MD5: 16 byte (tempo di hash 500 MB: 1462 ms)
  • SHA-1: 20 byte (1644 ms)
  • SHA256: 32 byte (5618 ms)
  • SHA384: 48 byte (3839 ms)
  • SHA512: 64 byte (3820 ms)
  • RIPEMD: 20 byte (7066 ms)

Ognuna di queste funzioni svolge in modo diverso; MD5 è il più veloce e RIPEMD il più lento.

MD5 ha il vantaggio di adattarsi al tipo Guid incorporato; ed è la base dell'UUID di tipo 3 . L'hash SHA-1 è la base dell'UUID di tipo 5.Il che li rende davvero facili da usare per l'identificazione.

MD5 è tuttavia vulnerabile agli attacchi di collisione , SHA-1 è anche vulnerabile ma in misura minore.

In quali condizioni dovrei usare quale algoritmo di hashing?

Le domande particolari a cui sono davvero curioso di vedere la risposta sono:

  • MD5 non è affidabile? In situazioni normali quando si utilizza l'algoritmo MD5 senza intenzioni dannose e nessuna terza parte ha intenzioni dannose ci si aspetterebbe QUALSIASI collisione (ovvero due byte arbitrari [] che producono lo stesso hash)

  • Quanto è meglio RIPEMD di SHA1? (se è meglio) è 5 volte più lento da calcolare ma la dimensione dell'hash è la stessa di SHA1.

  • Quali sono le probabilità di ottenere collisioni non dannose quando si esegue l'hashing di nomi di file (o altre stringhe brevi)? (Ad esempio 2 nomi di file casuali con lo stesso hash MD5) (con MD5 / SHA1 / SHA2xx) In generale, quali sono le probabilità di collisioni non dannose?

Questo è il benchmark che ho usato:

    static void TimeAction(string description, int iterations, Action func) {
        var watch = new Stopwatch();
        watch.Start();
        for (int i = 0; i < iterations; i++) {
            func();
        }
        watch.Stop();
        Console.Write(description);
        Console.WriteLine(" Time Elapsed {0} ms", watch.ElapsedMilliseconds);
    }

    static byte[] GetRandomBytes(int count) {
        var bytes = new byte[count];
        (new Random()).NextBytes(bytes);
        return bytes;
    }


    static void Main(string[] args) {

        var md5 = new MD5CryptoServiceProvider();
        var sha1 = new SHA1CryptoServiceProvider();
        var sha256 = new SHA256CryptoServiceProvider();
        var sha384 = new SHA384CryptoServiceProvider();
        var sha512 = new SHA512CryptoServiceProvider();
        var ripemd160 = new RIPEMD160Managed();

        var source = GetRandomBytes(1000 * 1024);

        var algorithms = new Dictionary<string,HashAlgorithm>();
        algorithms["md5"] = md5;
        algorithms["sha1"] = sha1;
        algorithms["sha256"] = sha256;
        algorithms["sha384"] = sha384;
        algorithms["sha512"] = sha512;
        algorithms["ripemd160"] = ripemd160;

        foreach (var pair in algorithms) {
            Console.WriteLine("Hash Length for {0} is {1}", 
                pair.Key, 
                pair.Value.ComputeHash(source).Length);
        }

        foreach (var pair in algorithms) {
            TimeAction(pair.Key + " calculation", 500, () =>
            {
                pair.Value.ComputeHash(source);
            });
        }

        Console.ReadKey();
    }

15
Il fatto che tu menzioni md5 si adatti al formato GUID (16 byte) suggerisce un malinteso fondamentale. Un hash non è garantito per essere unico, ma è raro (e difficile da falsificare se usato in senso crittografico) e derivato dalla cosa di cui è un hash mentre un GUID è, beh, unico ma non correlato al contenuto del cosa che identifica. Sono usati per scopi molto diversi.
Barry Wark,

1
Corretto, non correlato, è solo un fatto specifico di implementazione a portata di mano. Capisco che non è possibile inserire l'infinito in un 16 byte. Puoi ottenere collisioni con QUALSIASI algoritmo di hashing
Sam Saffron,

5
Anche un Guid è praticamente unico, in teoria se continuassi a generare Guide alla fine otterrai duplicati.
Sam Saffron,

3
Non dovresti davvero inserire un hash in un GUID, anche se si adatta. Esempio più semplice: due copie dello stesso file dovrebbero avere GUID diversi, ma lo stesso hash. Anche le prime 8 lettere del nome di una persona si adattano abbastanza bene a 16 byte.
dbkk,

2
@ user2332868 La rottura di SHA-1 non ha alcun effetto sulla probabilità di collisioni accidentali . Quando un intento dannoso è una minaccia per il tuo utilizzo, penso che scegliere ciecamente qualsiasi funzione di hash sia sbagliato e che tu debba dedicare del tempo a fare analisi dei rischi / costi per il tuo caso specifico.
Andrey Tarantsov,

Risposte:


138

Nella crittografia, le funzioni hash forniscono tre funzioni separate.

  1. Resistenza alla collisione : quanto è difficile per qualcuno trovare due messaggi ( due messaggi qualsiasi ) che abbiano lo stesso hash.
  2. Preimage Resistance : dato un hash, quanto è difficile trovare un altro messaggio che abbia lo stesso hash? Conosciuto anche come a funzione hash unidirezionale .
  3. Seconda resistenza preimage : dato un messaggio, trova un altro messaggio che abbia lo stesso hash.

Queste proprietà sono correlate ma indipendenti. Ad esempio, la resistenza alle collisioni implica una seconda resistenza preimmaginata, ma non viceversa. Per ogni data applicazione, avrai requisiti diversi, che richiedono una o più di queste proprietà. Una funzione hash per proteggere le password su un server richiede in genere solo la resistenza preimage, mentre i digest dei messaggi richiedono tutti e tre.

È stato dimostrato che MD5 non è resistente alle collisioni, tuttavia ciò non ne preclude l'uso in applicazioni che non richiedono resistenza alle collisioni. In effetti, MD5 viene spesso utilizzato in applicazioni in cui le dimensioni e la velocità della chiave più piccole sono vantaggiose. Detto questo, a causa dei suoi difetti, i ricercatori raccomandano l'uso di altre funzioni di hash in nuovi scenari.

SHA1 ha un difetto che consente di trovare collisioni in teoria molto meno dei 2 ^ 80 passi richiesti da una funzione hash sicura della sua lunghezza. L'attacco viene continuamente rivisto e attualmente può essere eseguito in ~ 2 ^ 63 passaggi - appena all'interno dell'attuale regno della calcolabilità. Per questo motivo NIST sta eliminando gradualmente l'uso di SHA1, affermando che la famiglia SHA2 dovrebbe essere utilizzata dopo il 2010.

SHA2 è una nuova famiglia di funzioni hash creata dopo SHA1. Attualmente non ci sono attacchi noti contro le funzioni SHA2. SHA256, 384 e 512 fanno tutti parte della famiglia SHA2, usando solo lunghezze di chiave diverse.

RIPEMD Non posso commentare troppo, tranne per notare che non è così comunemente usato come le famiglie SHA, e quindi non è stato esaminato così attentamente dai ricercatori crittografici. Per questo motivo da solo consiglierei l'uso delle funzioni SHA su di esso. Nell'implementazione che stai usando, sembra anche piuttosto lento, il che lo rende meno utile.

In conclusione, non esiste una migliore funzione: tutto dipende da ciò di cui hai bisogno. Siate consapevoli dei difetti di ciascuno e sarete in grado di scegliere la funzione di hash giusta per il vostro scenario.


1
Apprezzo molto che tu abbia approfondito questo livello di dettaglio. Questo è molto utile
Joelc,

1
Per alcune applicazioni, anche una funzione hash non crittografica potrebbe essere appropriata. L'OP non ha mai menzionato se fosse specificamente per le password, o per l'autenticazione della risposta alla sfida, o per i token di accesso o semplicemente per indicizzare un gruppo di stringhe / file. La prestazione, d'altra parte, è una preoccupazione per l'OP ...
Seva Alekseyev

111

Tutte le funzioni hash sono "rotte"

Il principio del buco del piccione dice che sforzati quanto vuoi che non puoi montare più di 2 piccioni in 2 buche (a meno che tu non li tagli). Allo stesso modo non è possibile inserire 2 ^ 128 + 1 numeri in 2 ^ 128 slot. Tutte le funzioni hash generano un hash di dimensioni finite, ciò significa che puoi sempre trovare una collisione se cerchi tra "sequenze di dimensioni finite" + 1 sequenze. Non è possibile farlo. Non per MD5 e non per Skein .

MD5 / SHA1 / Sha2xx non hanno collisioni casuali

Tutte le funzioni hash hanno collisioni, è un fatto della vita. Incontrare queste collisioni per caso equivale a vincere alla lotteria intergalattica . Vale a dire nessuno vince la lotteria intergalattica , non è proprio il modo in cui funziona la lotteria. Non incontrerai mai un hash MD5 / SHA1 / SHA2XXX accidentale, MAI. Ogni parola in ogni dizionario, in ogni lingua, ha un valore diverso. Ogni nome di percorso, su ogni macchina nell'intero pianeta ha un diverso hash MD5 / SHA1 / SHA2XXX. Come faccio a saperlo, potresti chiedere. Bene, come ho detto prima, nessuno vince mai la lotteria intergalattica.

Ma ... MD5 è rotto

A volte il fatto che sia rotto non ha importanza .

Allo stato attuale non sono noti attacchi pre-immagine o seconda pre-immagine su MD5.

Allora, cosa c'è di così rotto in MD5, potresti chiedere? È possibile che una terza parte generi 2 messaggi, uno dei quali è MALE e un altro è BUONO che entrambi hanno lo stesso valore. ( Attacco di collisione )

Tuttavia, l'attuale raccomandazione RSA non è di utilizzare MD5 se è necessaria una resistenza pre-immagine. Le persone tendono a sbagliare per precauzione quando si tratta di algoritmi di sicurezza.

Quindi quale funzione hash dovrei usare in .NET?

  • Usa MD5 se hai bisogno della velocità / dimensione e non ti importa degli attacchi di compleanno o degli attacchi pre-immagine.

Ripeti questo dopo di me, non ci sono possibilità di collisioni MD5 , le collisioni dannose possono essere attentamente progettate. Anche se finora non sono noti attacchi pre-immagine su MD5, la linea degli esperti di sicurezza è che MD5 non dovrebbe essere usato dove è necessario difendersi dagli attacchi pre-immagine. SAME vale per SHA1 .

Tieni presente che non tutti gli algoritmi devono difendersi da attacchi pre-immagine o di collisione. Prendi il banale caso di una ricerca di primo passaggio per file duplicati sul tuo HD.

  • Utilizzare la funzione basata su SHA2XX se si desidera una funzione hash crittograficamente sicura.

Nessuno ha mai trovato alcuna collisione SHA512. MAI. Ci hanno provato davvero tanto. Del resto nessuno ha mai trovato collisioni tra SHA256 e 384. .

  • Non utilizzare SHA1 o RIPEMD se non per uno scenario di interoperabilità.

RIPMED non ha ricevuto la stessa quantità di controllo che hanno ricevuto SHAX e MD5. Sia SHA1 che RIPEMD sono vulnerabili agli attacchi di compleanno. Sono entrambi più lenti di MD5 su .NET e hanno dimensioni scomode di 20 byte. È inutile usare queste funzioni, dimenticarsene.

Gli attacchi di collisione SHA1 sono scesi a 2 ^ 52, non sarà troppo lungo fino a quando le collisioni SHA1 non si scatenano.

Per informazioni aggiornate sulle varie funzioni hash, dai un'occhiata allo zoo delle funzioni hash .

Ma aspetta, c'è di più

Avere una funzione hash veloce può essere una maledizione. Ad esempio: un utilizzo molto comune per le funzioni hash è la memorizzazione delle password. In sostanza, si calcola l'hash di una password combinata con una stringa casuale nota (per impedire gli attacchi dell'arcobaleno) e si memorizza tale hash nel database.

Il problema è che se un utente malintenzionato ottiene un dump del database, può indovinare in modo abbastanza efficace le password usando la forza bruta. Ogni combinazione che prova richiede solo una frazione di millisecondo e può provare centinaia di migliaia di password al secondo.

Per ovviare a questo problema, è possibile utilizzare l'algoritmo bcrypt , progettato per essere lento in modo che l'attaccante venga fortemente rallentato se si attacca un sistema utilizzando bcrypt. Di recente scrypt ha fatto notizia ed è considerato da alcuni più efficace di bcrypt ma non conosco un'implementazione .Net.


Mentre sia MD5 che SHA-1 sono stati indeboliti, MD5 è molto più debole di SHA-1, mentre solo leggermente più veloce. Le collisioni MD5 effettive sono state trovate e utilizzate per exploit nel mondo reale (falsificazione di certificati CA), ma per quanto ne so non sono state rilevate collisioni SHA-1 effettive (sebbene il numero di operazioni sia stato notevolmente ridotto dalla forza bruta). E dato quanto MD5 è più debole, non sarei sorpreso se gli attacchi di seconda immagine prima apparissero prima per MD5 che per SHA-1. Quindi, penso che dovresti usare SHA-1 se hai bisogno di velocità e non di resistenza alle collisioni, e altrimenti usi una della famiglia SHA-2.
Brian Campbell,

1
@Brian è abbastanza chiaro che nei prossimi anni le persone saranno in grado di eseguire attacchi di collisione su SHA1, questo renderà SHA1 efficace quanto MD5, La cosa del certificato CA è un attacco di collisione, così in pochi anni le persone saranno in grado per eseguire lo stesso attacco sui certificati CA SHA1. L'attacco dipende dal fatto che una parte malvagia crea un MALE e un BUONO certificato. Non ci sono attacchi di primage noti su MD5 e il fatto che ci siano attacchi di collisione non rende più o meno probabili gli attacchi pre-immagine.
Sam Saffron,

È molto meno su quale hash usi per le password, che su ciò che è hash. Se il tuo sale è noto, il tuo database è immediatamente vulnerabile a un attacco del dizionario; se il tuo sale è procedurale e il tuo filesystem è compromesso, sei (di nuovo) vulnerabile; se il tuo sale viene omesso, sei di nuovo compromesso. La sicurezza in questione è, a prescindere da cosa, CHE COSA è l'hash. Certificati, non mi rivolgerò perché non li ho trattati come programmatore (IE, creazione, comprensione, ecc.).
Robert K,

Il termine spezzato ha un significato specifico nel contesto dell'hashing e non è il significato su cui questa risposta pone l'accento. Tutto ciò che questa risposta farà è causare confusione.
Joel McBeth

1
Questa è una risposta eccellente perché si concentra sulla praticità. Gli hash sono usati per cose diverse dalla sicurezza (come la generazione di chiavi di ricerca cache per dati non sensibili o la determinazione di un oggetto serializzato è cambiato). Le possibilità di un attacco mirato sono praticamente pari a zero (mai dire mai) e, anche se un attacco avesse successo, non avrebbe alcun impatto materiale. Ottimo lavoro incentrato sull'impatto pratico (anziché teorico).
DVK,

35

Aggiornare:

I tempi sono cambiati, abbiamo un vincitore SHA3. Consiglierei di usare Keccak (aka SHA3 ) vincitore del concorso SHA3.

Risposta originale:

In ordine di più debole a più forte direi:

  1. RIPEMD BROKEN, Non dovrebbe mai essere usato come si può vedere in questo pdf
  2. MD-5 BROKEN, non dovrebbe mai essere usato, può essere rotto in 2 minuti con un laptop
  3. SHA-1 ROTTO, non dovrebbe mai essere usato, è rotto in linea di principio, gli attacchi stanno migliorando di settimana in settimana
  4. SHA-2 WEAK, probabilmente verrà rotto nei prossimi anni. Sono stati riscontrati alcuni punti deboli.Si noti che generalmente la dimensione della chiave più alta, più difficile è la funzione hash da interrompere. Mentre la dimensione chiave = forza non è sempre vera, è per lo più vera. Quindi SHA-256 è probabilmente più debole di SHA-512.
  5. Skein NO KNAKNESSES CONOSCIUTO, è un candidato per SHA-3 . È abbastanza nuovo e quindi non testato. È stato implementato in diverse lingue.
  6. MD6 NESSUNA DEBOLEZZA CONOSCIUTA, è un altro candidato per SHA-3. Probabilmente più forte di Skien, ma più lento su macchine single core. Come Skien non è stato testato. Alcuni sviluppatori attenti alla sicurezza lo stanno utilizzando, in ruoli mission-critical .

Personalmente userei MD6, perché non si può mai essere troppo paranoici. Se la velocità è una vera preoccupazione guarderei Skein, o SHA-256.


5
Non inserirò Skein e MD6 così in alto nella lista; c'è una ragione per cui la competizione SHA-3 non sarà finita fino alla fine del 2012. Ci vuole molto tempo e molti occhi per essere convinti che una funzione di hash sia effettivamente sicura, e nessuna di queste funzioni sono già stati abbastanza a lungo per quello.
Eric Burnett,

Sono d'accordo con i tuoi sentimenti, ma penso che la comunità si trovi in ​​una strana posizione. Tutte le funzioni hash in uso sono pericolosamente vicine alla rottura (forse, forse, non SHA2 256-512) e tuttavia dobbiamo aspettare fino al 2012 per scegliere una sostituzione. scegli il tuo veleno: debole / rotto o non testato (la maggior parte dei candidati NIST non è pubblica da più di 6 mesi)? Scelta difficile.
Ethan Heilman,

5
RIPEMD è rotto, ma RIPEMD-128/160/256 sono diversi e non sono rotti.
Bwooce,

Non sono a conoscenza di implementazioni performanti di Skein per .NET. Ho incontrato SkeinFish e nskein, ed entrambi sono stati molto lenti.
Cocowalla,

1
Aspetterei con l'utilizzo di SHA-3 fino a quando lo standard attuale non sarà disponibile, almeno se si desidera effettivamente seguire uno standard. L'algoritmo stesso ha troppe opzioni.
Paŭlo Ebermann,

3

A difesa di MD5, non esiste un modo noto per produrre un file con un hash MD5 arbitrario. L'autore originale deve pianificare in anticipo per avere una collisione funzionante. Pertanto, se il destinatario si fida del mittente, MD5 va bene. MD5 viene interrotto se il firmatario è dannoso, ma non è noto per essere vulnerabile agli attacchi man-in-the-middle.


1
Anche se non sono affatto un esperto in questo campo, al giorno d'oggi non è quasi possibile calcolare hash MD5 arbitrari con la forza bruta?
mafu,

@mafu: risposta tardiva qui, ma è possibile calcolare qualsiasi hash tramite forza bruta. Potrebbe volerci davvero molto tempo.
Warty,

@ItzWarty Mi riferivo in particolare al tempo necessario - poiché MD5 è piuttosto breve, ho pensato che fosse possibile semplicemente lanciare su di esso una fonte di calcolo ragionevole (E3, o una griglia di computer economica alcune macchine con poche schede grafiche, qualcosa lungo quelle linee) ed essere in grado di calcolare un hash MD5 arbitrario entro, diciamo, pochi giorni.
mafu,

@mafu Un attacco pre-immagine costa 2 ^ 127 invocazioni di hash per un hash a 128 bit. Questo è tutt'altro che fattibile. 2 ^ 80 invocazioni sono fattibili ma già molto costose.
Codici

2

Quello che usi davvero dipende da cosa lo stai usando. Se vuoi solo assicurarti che i file non vengano danneggiati durante il trasporto e che non siano così preoccupati per la sicurezza, vai veloce e piccolo. Se hai bisogno di firme digitali per accordi di salvataggio federali da svariati miliardi di dollari e devi assicurarti che non siano falsi, cerca di falsificare e rallentare.


1
Molte volte quando parlo di soluzioni al problema menziono che uso MD5 per una rapida identità (hashing di una stringa), dicono "ma md5 è rotto ... non usarlo, usa sha1" ... Non mi iscrivo davvero a questo, mi chiedevo se qualcosa è così fondamentalmente rotto con alcuni degli hash più deboli che dovrebbero essere evitati ... ad esempio casi di lavori reali in cui i dati normali producono collisioni
Sam Saffron,

Visto che MD5 ha funzionato bene per milioni di persone per quindici anni, ho il sospetto che vada bene per te se la sicurezza dell'hash non è cruciale.
mqp

2
@sambo MD5 funziona perfettamente per quasi tutti i casi, tranne quando l'effettiva sicurezza / integrità del sistema dipende dalla prevenzione delle collisioni.
Rex M

2

Vorrei rinviare (prima che md5 venga distrutto) che uso ancora ampiamente md5 nonostante la sua schiacciante rottura per un sacco di criptovalute.

Fintanto che non ti interessa proteggere dalle collisioni (sei comunque sicuro di usare md5 in un hmac) e vuoi la velocità (a volte vuoi un hash più lento) allora puoi comunque usare md5 con sicurezza.


@Mike Sono con te su questo, che era un po 'quello per cui stavo scavando con questa domanda, è qualcosa sulle funzioni di hash più deboli così fondamentalmente rotte che non dovrebbero mai essere usate.
Sam Saffron,

Inoltre, se i dati o la sicurezza richiesta dei dati hanno una durata inferiore al periodo di crack (pochi minuti in questi giorni) MD5 va assolutamente bene. Il punto è utile dal punto di vista della situazione ma comunque utile.
annakata,

@annakata: tieni presente che dovresti anche evitare di riutilizzare le chiavi su più messaggi perché sia ​​utilizzabile in tali circostanze.
Steve Westbrook,

2

Sarebbe una buona idea dare un'occhiata all'algoritmo BLAKE2 .

Come è descritto, è più veloce di MD5 e almeno sicuro come SHA-3. È inoltre implementato da diverse applicazioni software , tra cui WinRar.


Potrebbe essere più veloce, tranne che molte implementazioni hanno il supporto hardware che rende SHA-256 abbastanza veloce.
zaph,

Sono d'accordo. a partire dal 2019, Blake2b è il miglior hash general-purpose rilasciato fino ad oggi. Significativamente più veloce di tutte le altre alternative, e non meno sicuro (non in alcun modo significativo almeno), e può essere eseguito in soli 336 byte di ram (168 per blake2s), oh, ed è ottimizzato per CPU little-endian, che è l'endiano dominante sui sistemi di oggi.
Hanshenrik,

0

Non sono un esperto in questo genere di cose, ma tengo il passo con la comunità della sicurezza e molte persone lì considerano l'hash md5 rotto. Direi che quale usare dipende dalla sensibilità dei dati e dall'applicazione specifica. Potresti riuscire a cavartela con un hash leggermente meno sicuro purché la chiave sia buona e potente.


1
le funzioni hash in genere non usano i tasti
Ethan Heilman,

0

Ecco i miei suggerimenti per te:

  1. Probabilmente dovresti dimenticare MD5 se prevedi gli attacchi. Ci sono molti tavoli arcobaleno per loro online e aziende come la RIAA sono state conosciute per essere in grado di produrre sequenze con hash equivalenti.
  2. Usa un sale se puoi. Includere la lunghezza del messaggio nel messaggio può rendere molto difficile fare una collisione hash utile.
  3. Come regola generale, più bit significa meno collisioni (secondo il principio del buco del piccione) e più lento e forse più sicuro (a meno che tu non sia un genio della matematica che può trovare vulnerabilità).

Vedi qui per un documento che descrive in dettaglio un algoritmo per creare collisioni md5 in 31 secondi con un computer desktop Intel P4.

http://eprint.iacr.org/2006/105


Questo commento è molto antico e sembra piuttosto sepolto, ma questo pezzo - la RIAA è stata conosciuta per essere in grado di produrre sequenze con hash equivalenti - mi è saltato fuori di testa, e sono molto curioso di sapere quale fosse il contesto. In particolare, MD5 bruteforcing 8 anni fa era un po 'meno banale rispetto al 2017, quindi devono aver avuto una ragione abbastanza buona.
i336_
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.