it-swarm.dev

Come funziona l'hashing?

Sono stato interessato alla sicurezza delle informazioni. Mi è stata recentemente presentata l'idea di hashing. Ciò che attualmente capisco sull'hash è che richiede la password immessa da un utente. Quindi genera casualmente un "hash" usando un mucchio di variabili e mescolando tutto. Quindi, quando si immette questa password per accedere, la password corrisponde all'hash. Ci sono solo un paio di cose che non capisco al riguardo.

  1. Perché è così difficile rompere questi hash? Suppongo che una volta trovato il metodo che stanno usando per crittografarlo (lasciamo andare un metodo estremamente semplice come il codice di Cesare una volta scoperto quanti ne devi spostare puoi farlo per interi libri). Anche se usa qualcosa come il tempo e lo confonde ci sono alcuni modi davvero grandi che puoi limitare le opzioni (Usiamo la cifra di Cesare che stanno usando l'anno mod x sai già che ci sono due anni possibili realisticamente, quindi devi solo capire il secondo pezzo del puzzle).

  2. Se vengono generati casualmente (anche se due password sono uguali, escono in modo diverso) come possono sapere se è corretta?

  3. Come sono craccati. Come fa hash cat a sapere se ha decrittografato correttamente la password?

Video correlato (ma non risponde esattamente alla mia domanda): https://www.youtube.com/watch?v=b4b8ktEV4Bg

79
Griffin Nowak

Veloce, fattore 1081.

O se preferisci, rispondi a questa domanda: che cosa è 23 volte 47?

Quale è più facile? È più semplice eseguire una moltiplicazione (basta seguire le regole meccanicamente) che recuperare gli operandi dati solo il prodotto. Moltiplicazione. (A proposito, questo è il fondamento di alcuni algoritmi crittografici come RSA .)

Funzioni hash crittografiche hanno basi matematiche diverse, ma hanno la stessa proprietà: sono facili da calcolare andando avanti (calcola H(x) dato x), ma praticamente impossibile calcolare andando indietro (dato y, calcola x tale che H(x) = y). Infatti, uno dei segni di una buona funzione di hash crittografico è che non c'è modo migliore per trovare x che provarli tutti e calcolare H(x) fino a trovare una corrispondenza.

Un'altra importante proprietà delle funzioni hash è che due input diversi hanno hash diversi. Quindi se H (x1) = H (x2), possiamo concludere che x1 = x2. Matematicamente parlando, questo è impossibile - se gli input sono più lunghi della lunghezza dell'hash, ci devono essere delle collisioni. Ma con una buona funzione hash crittografica, non esiste un modo noto per trovare una collisione con tutte le risorse informatiche del mondo.

Se vuoi saperne di più sulle funzioni hash crittografico , leggi questa risposta di Thomas Pornin . Dai, aspetterò.

Si noti che una funzione hash non è una funzione di crittografia. La crittografia implica che è possibile decrittografare (se si conosce la chiave). Con un hash, non esiste un numero magico che ti consente di tornare indietro.

Le principali funzioni hash crittografiche consigliate sono SHA-1 e la famiglia SHA-2 (disponibile in diverse dimensioni di output, principalmente SHA-256 e SHA-512). MD5 è più vecchio, ora deprecato perché ha conosciuto collisioni. In definitiva, non vi è alcuna prova matematica che siano effettivamente buone funzioni di hash crittografico, solo una credenza diffusa perché molti crittografi professionisti hanno trascorso anni della loro vita cercando e fallendo di romperli.

Ok, questa è una parte della storia. Ora un hash password non è direttamente una funzione hash crittografica. Una funzione hash password (PHF) accetta due input: la password e un valore salt. Il salt viene generato casualmente quando l'utente sceglie la sua password, e viene memorizzato insieme alla password con hash PHF (password, salt). (Ciò che conta è che due account diversi abbiano sempre sali diversi e generare casualmente un sale sufficientemente grande è un buon modo per avere questa proprietà con una probabilità schiacciante.) Quando l'utente accede nuovamente, il sistema di verifica legge il sale dal database delle password , calcola PHF (password, salt) e verifica che il risultato sia ciò che è archiviato nel database.

Il punto è che se qualcuno vuole decifrare una password, dovranno conoscere l'hash prima di poter iniziare e dovranno attaccare ogni account separatamente. Il sale rende impossibile eseguire molti lavori di cracking in anticipo, ad es. generando un Rainbow table .

Ciò risponde (2) e (3) - il verificatore legittimo e l'attaccante scoprono allo stesso modo se la password (inserita dall'utente o indovinata dall'attaccante) è corretta. Un ultimo punto della storia: una buona funzione di hash della password ha una proprietà aggiuntiva, deve essere lenta. Il server legittimo deve calcolarlo solo una volta per tentativo di accesso, mentre un attaccante deve calcolarlo una volta per ipotesi, quindi la lentezza fa più male all'attaccante (il che è necessario, perché l'attaccante in genere ha più hardware specializzato).

Se hai mai bisogno di hash password, non inventare il tuo metodo . sa uno dei metodi standard : scrypt , bcrypt o PBKDF2 .

Funzioni hash crittografiche sono oggetti matematici che possono essere descritti come "un grande mix e rimescolamento di alcuni bit". Prendono come input una sequenza di bit (possibilmente molto lunga) e offrono un output di dimensioni fisse. In parole povere, sono così aggrovigliati che sebbene non ci sia nulla di segreto in loro (che è solo un codice deterministico), nessuno può capire come "invertirli" (trovare un input corrispondente per un determinato output) se non con il metodo di base chiamato "fortuna ": prova input casuali fino a quando non viene trovata una corrispondenza.

Come può accadere, scientificamente, che funzioni di hash possano esistere affatto è na buona domanda .

L'hash non è una crittografia . Non c'è segreto, nessuna chiave nell'hash.

Le funzioni hash hanno molti usi; uno di questi è "memorizzazione password". Una funzione hash sembra una buona cosa per l'archiviazione della password. Non vogliamo archiviare direttamente le password (altrimenti una sbirciata occasionale nei nostri database da parte dell'attaccante gli darebbe troppe informazioni; vedi questo post sul blog per una discussione); vogliamo memorizzare token di verifica password: qualcosa che consente la verifica di una password (che l'utente presenta) ma non rivela la password stessa. Quindi l'idea è: memorizziamo l'hash della password. Quando una password deve essere verificata, ne calcoliamo solo l'hash e vediamo se corrisponde al valore memorizzato. Ma indovinare la password solo dal valore hash è difficile, poiché la funzione hash è resiliente contro "inversione" (vedi sopra).

Poiché le password sono un tipo speciale di dati (ovvero dati che gli umani possono ricordare), per una corretta sicurezza, abbiamo bisogno di una funzione hash "rafforzata":

  • Vogliamo una funzione hash molto lenta.
  • Non vogliamo one funzione hash, ma many funzioni hash distinte, in modo che ogni password venga hash con la sua funzione hash; si tratta di dissuadere gli attacchi paralleli. Questo processo di trasformazione di una singola funzione hash in molte varianti è chiamato salting.

Vedi questa risposta per un trattamento completo dell'argomento delle password di hashing.

32
Thomas Pornin

L'hash è una funzione da una stringa di bit (generalmente di lunghezza variabile) a un'altra stringa di bit (di solito più piccola e di lunghezza fissa).

L'hashing viene utilizzato nei database per il recupero dei dati e nelle strutture di dati in memoria chiamate tabelle hash. Ci consente di ridurre i dati arbitrari, come una stringa di caratteri o un oggetto complicato con molti campi, a un numero binario che può quindi essere utilizzato direttamente come indice in una matrice sparsa per recuperare i dati associati (con alcuni dettagli per la gestione dell'hash collisioni).

Le funzioni di hashing utilizzate nel modo sopra descritto sono "cugini" di funzioni di hashing crittografiche. Sono progettati per esigenze diverse. Devono essere veloci da calcolare e raggiungere una buona distribuzione.

Nell'informatica sicura, gli hash crittografici vengono utilizzati per digerire i dati in alcune stringhe di bit rappresentative. Le funzioni crittografiche hanno requisiti diversi. Sono progettati per essere difficili da invertire (per essere funzioni "botola" o "a senso unico"). Non solo, ma un requisito importante è che deve essere difficile trovare, per un dato testo in chiaro e valore di hash, un altro testo in chiaro che produce lo stesso hash.

L'hashing può essere utilizzato non solo per le password, ma come checksum per la verifica dell'integrità dei dati e come parte dell'implementazione delle firme digitali. Per firmare digitalmente un documento di grandi dimensioni, dobbiamo semplicemente eseguire l'hashing del documento per produrre un "digest" (un nome utilizzato per l'output di una funzione di hashing, quando viene eseguito il hash di qualcosa di molto lungo). Quindi proprio questo digest viene messo attraverso il sistema crittografico a chiave pubblica per produrre una firma. Qui puoi vedere la debolezza: cosa succede se un utente malintenzionato riesce a produrre un documento con lo stesso digest? Quindi sembra che la firma originale prodotta sul documento originale sia in realtà una firma di un documento contraffatto: una contraffazione che ha trapiantato una firma è stata effettivamente perpetrata.

L'hash della password consente ai sistemi di non memorizzare la versione in testo semplice di una password, ma consente loro di verificare se l'utente che sta cercando di ottenere la voce conosce quella password. L'hash non solo consente ai sistemi di non archiviare le password in testo normale (che dovrebbero essere custodite con molta attenzione) ma consente la possibilità che, anche se gli hash sono esposti pubblicamente, le password sono ancora sicure (analogamente al modo in cui la crittografia a chiave pubblica i sistemi sono in grado di rivelare le chiavi pubbliche). Sebbene in pratica, gli hash siano comunque protetti dall'accesso del pubblico: ad esempio /etc/shadow file su sistemi simili a Unix, che integrano leggibili in tutto il mondo /etc/passwd File.

La funzione di hashing è tutt'altro che casuale. Tuttavia, la randomizzazione viene utilizzata per contrastare gli aggressori che creano grandi dizionari di password e hash, che consentono loro di cercare un codice hash e recuperare la password corrispondente.

Per eseguire l'hashing di una password in modo più sicuro, possiamo semplicemente aggiungere alcuni bit casuali ad essa chiamati "salt". Sali diversi aggiunti alla stessa password, ovviamente, portano a hash diversi (si spera con poche o nessuna collisione).

Se il salt casuale è, diciamo, largo 32 bit, significa che, in teoria, una password può avere un hash in oltre quattro miliardi di modi diversi, il che rende molto poco pratico avere un dizionario precompilato di tutti i possibili hash di un gran numero di password.

Naturalmente, quando l'utente viene autenticato, non sa nulla di questo sale. Va bene perché il sale è memorizzato insieme all'hash nel profilo dell'utente (spesso, combinato con l'hash in una singola stringa di bit compatta). Quando la password dell'utente viene convalidata, il salt viene aggiunto a qualsiasi password inserita, in modo che l'hash sia eseguito con il salt corretto. Se la password è corretta, l'hash corrisponderà, poiché anche il salt in uso è quello giusto, essendo stato estratto dal profilo dell'utente.

È così che la casualità è incorporata nell'hash delle password, pur permettendo che funzioni.

Ciò che rende gli hash difficili da decifrare è che sono costruiti con funzioni "botola" o "a senso unico". In matematica, ci sono molti esempi di tali cose. Ad esempio, la semplice aggiunta è una botola. Se aggiungiamo alcuni numeri interi per produrre una somma, è impossibile recuperare i numeri originali, conoscendo solo la somma.

Gli hash delle password non sono password crittografate. Se un utente malintenzionato ha l'hash e il salt di una password, e capita di indovinare la password, allora può facilmente confermarlo, esattamente allo stesso modo in cui lo fa il software di autenticazione del login: esegue la password e il sale attraverso la funzione di hashing e vede che emerge l'hash corretto.

19
Kaz

Una delle chiavi dell'hashing è che elimina le informazioni. Non puoi invertire un hash perché la conoscenza necessaria è sparita. Ecco alcuni esempi di funzioni di hashing praticabili (ma piuttosto inutili). Se mi dai una password, potrei fare qualcosa del tipo:

  • Conta il numero di vocali
  • Prendi il ASCII per ogni lettera e XOR tutti insieme)
  • Prendi il checksum CRC32 della rappresentazione binaria della password (questo in realtà è un vero hash, non solo crittografico)

In ognuno di questi casi, non posso invertire il processo. Invece, devo rieseguire il processo quando mi dai nuovamente la password per vedere se il calcolo che ho eseguito corrisponde.

Ad esempio: se inizialmente mi dai la password "scimmia" potrei memorizzare il numero 3 (3 vocali). Quindi, più tardi, quando provo ad autenticare la password "dragon", eseguo di nuovo lo stesso controllo e ne trovo 2, che non corrisponde a 3. Quindi so che mi hai dato la password sbagliata. Ma se mi dai la password "melissa", presumo erroneamente che tu abbia digitato la password giusta. Questa è una collisione di hash .

L'insieme di regole che applichi per trovare il numero che rappresenta una determinata password è la tua funzione hash . Queste sono considerate funzioni "a senso unico" perché non dovresti essere in grado di annullarle. Le funzioni hash di alta qualità sono progettate per limitare il numero di potenziali collisioni, in modo da non doversi preoccupare di quel problema. Un ulteriore passo avanti, funzioni hash crittografiche sono progettate per rendere difficile trovare una stringa che potrebbe corrispondere a un determinato output (e forse creare intenzionalmente collisioni) . Sono inoltre progettati per limitare la quantità di informazioni che è possibile raccogliere su un determinato input solo dall'output hash.

Di conseguenza, l'unico modo per dire quale password corrisponde a un determinato hash crittografico è provare tutte le possibilità fino a quando non ti imbatti in una che funziona. Ulteriori contromisure (salt, BPKDF2, ecc.) Rendono ancora più difficile questo processo di indovinando la persona che indovina la password passa attraverso più cerchi per ogni tentativo.

Nota che ho completamente chiarito come una funzione di crittografia crittografica rende difficile trovare una password funzionante (anche se non è quella originale). Questo è chiamato " attacco preimage ". Nell'esempio banale sopra, trovare "melissa" come password candidata contenente 3 vocali è un esempio di tale attacco.

Le funzioni hash crittografiche in genere lo fanno eseguendo l'input attraverso diversi "round" di un dato processo, in cui l'output di ciascun round diventa parte dell'input al successivo. Per capire l'input del primo round, dovresti capire l'input del secondo round, che a sua volta richiede di capire l'input del terzo round, ecc., Il che significa che ogni ipotesi di ciascun componente deve essere verificato attraverso una serie lunga e complessa di calcoli. Thomas Pornin ha una bella spiegazione esaustiva di come funziona questa resistenza; lettura piuttosto utile se vuoi capirla davvero.

11
tylerl
  1. Determina il valore costante di z che soddisfa questa equazione: xy ^ 7 + yz ^ 5 + x ^ 3z = 0. Hai bisogno di aiuto? OK, x = 32. Non riesci ancora a risolverlo? Quindi non dovresti conoscere la risposta in primo luogo.

    Il valore di y, che lo ridurrà a una singola equazione variabile, rendendo banale risolverlo per quella singola variabile per qualsiasi studente di 6 ° grado (possibilmente necessitando di una calcolatrice), è un segreto che ho condiviso solo con persone di cui mi fido. Senza di essa, z potrebbe essere qualsiasi cosa; il suo valore dipende da y e quindi non può essere risolto in modo soddisfacente senza un y costante e noto. Se non conosci il valore di y, è perché non mi fido abbastanza di te da dartelo in privato.

    Questo è il principio base della crittografia; la formula matematica o altro processo deterministico è ben documentato e una o più delle possibili variabili della formula possono anche essere conosciute pubblicamente, consentendo alle due parti di concordare un modo per impostare i loro codici in modo che ciascuno possa decrittografare cosa crittografa l'altro. Tuttavia, due variabili rimangono segrete; se ne conosci uno, puoi scoprire l'altro. Quello che dovresti sapere è la chiave, e quello che puoi scoprire con la chiave è il messaggio.

    Per un hash, è un po 'diverso. Un hash non richiede il mantenimento di un segreto per mantenerne un altro. Invece, gli hash funzionano in base a una trasformazione matematica irreversibile; per qualsiasi H(x) = y, non è noto H-1(y) = x tranne che per provare H(x) per tutte le possibili x fino a quando non ottieni y. Di solito, questo perché diversi risultati intermedi dell'equazione sono ambigui; ad esempio, calcolare il quadrato la radice di un numero positivo produce tecnicamente sia un risultato positivo che negativo, poiché entrambi i numeri potrebbero essere moltiplicati per se stesso per produrre il risultato. L'inverso di un modulo è similmente ambiguo; il numero 1, prodotto da x mod 3, avrebbe potuto essere prodotto da qualsiasi x = 3k + 1. Questi tipi di trasformazioni "unidirezionali" sono combinati in modo tale che il tentativo di calcolare la funzione di hash inversa genera infinite possibilità; il modo più semplice (più semplice) per risolverli è quindi semplicemente provare ogni possibile input fino a quando un output corrisponde. Ciò richiede ancora molto tempo.

  2. Gli hash non sono casuali. Come ho affermato in precedenza, gli hash sono il risultato di un'operazione matematica irreversibile. Tale operazione deve essere ancora deterministica; dato un input costante, l'output è costante indipendentemente da quante volte si esegue l'operazione. Non esiste un componente casuale.

    Dove potresti essere stato confuso è il termine per ciò che simula un hash, che è un Oracle casuale. Immagina una scatola nera, all'interno della quale è un ometto con una memoria fotografica e un metodo mistico per generare numeri perfettamente casuali. Scrivi qualcosa su un pezzo di carta e lo spingi attraverso una fessura in cui l'uomo lo prende. Lo legge e succede una delle due cose. O non l'ha mai letto prima, nel qual caso genererà un nuovo numero casuale e te lo darà, impegnando sia il tuo messaggio che il numero in sua memoria. Oppure, ha ha letto questo messaggio esatto prima, nel qual caso ricorda il numero che ha generato la prima volta che lo ha letto e ti dà il numero. Il generatore di numeri casuali non genererà mai un numero che ha già generato, ha una grandezza infinita possibile e la memoria del piccolo uomo è illimitata e infallibile. Pertanto, l'omino non penserà mai di aver letto un messaggio prima se non lo ha mai fatto, non dimenticherà mai di aver letto un messaggio prima, e quindi non produrrà mai e poi mai due numeri diversi per lo stesso identico messaggio né lo stesso numero per due diversi messaggi.

    Questo è ciò che le funzioni hash cercano di simulare. Non possono modellare questo piccolo uomo con la memoria fotografica, perché ciò richiederebbe uno spazio di archiviazione infinito e una disponibilità illimitata e universale, anche a dispositivi che non sono collegati a nessun altro dispositivo in nessun altro modo. Invece, si basano su un calcolo deterministico ma casuale -guardare che "digerisce" il messaggio nel suo valore di hash. La stessa funzione hash, dato lo stesso messaggio, produrrà lo stesso digest; tuttavia, queste funzioni sono limitate nel numero di valori hash che possono restituire. Questo crea la possibilità di ciò che chiamiamo collisioni di hash; ci sono più messaggi possibili che valori di hash, quindi prima o poi (si spera più tardi), due diversi messaggi produrranno lo stesso hash.

  3. Gli hash possono essere violati per tre motivi fondamentali. Primo, poiché sono una derivazione matematica deterministica del loro messaggio, i matematici (e quindi gli attaccanti) alla fine trovano una relazione matematica tra un messaggio e il suo hash, o tra due messaggi e i loro hash risultanti. Ciò che una volta era casuale non è più così. Ciò consentirebbe una serie di attacchi in base alla natura della debolezza riscontrata; se esiste un modo algoritmico, dato un messaggio e il suo hash, per generare un messaggio in collisione, questo è un problema. Se esiste un modo per manipolare un messaggio e prevedere l'hash risultante, questo è un problema diverso. Se esiste in effetti un modo per invertire l'hash, producendo un messaggio dall'hash che, quando ri-hash, produce lo stesso hash, questo è un problema serio.

    In secondo luogo, poiché gli hash hanno una dimensione digest limitata, prima o poi, due messaggi produrranno lo stesso hash. Ciò significa che un attaccante non deve trovare il messaggio che usi per produrre un certo hash; tutto quello che deve fare è trovare a messaggio che produce lo stesso hash. Le probabilità sono minime, teoricamente una possibilità su quanti possibili hash ci siano, ma comunque meglio di una all'infinito.

    Infine, mentre ci sono molti messaggi possibili, c'è un numero molto più piccolo di probabile messaggi. I messaggi che in genere forniamo alle funzioni hash di solito hanno una struttura (basata su lingua, oggetto, formattazione elettronica e scopo), il che significa che, data una parte del messaggio, possiamo indovinare più accuratamente altre parti del messaggio. Ciò significa, in termini di scienza dell'informazione, che i messaggi che vengono convertiti in hash hanno spesso entropia inferiore alla funzione di hash stessa; in parole povere, una funzione hash che produce digest a 256 bit può teoricamente produrre qualsiasi permutazione di quei bit, 2 ^ 256. Tuttavia, se ci sono, per esempio, solo 10.000 possibili messaggi che potrebbero mai essere immessi in questa funzione di hash da un sistema studiato per l'attacco, allora solo 10.000 dei 2 ^ 256 possibili valori di hash saranno mai visti e, cosa più importante, un l'attaccante dovrebbe, nel peggiore dei casi, provare solo tutti i 10.000 possibili input per trovare quello che produce il valore di hash che sta cercando.

5
KeithS