Domanda:
Perché improvvisare la tua funzione hash dalle funzioni hash esistenti è così male
George Powell
2013-04-01 06:24:02 UTC
view on stackexchange narkive permalink

Temo che mi verranno lanciati dei pomodori per aver fatto questa vecchia domanda, ma ecco qua.

Dopo aver letto che è pericoloso inventare l'hash della propria password dalle funzioni di hashing esistenti sopra e sopra ancora non riesco a capire la logica. Ecco alcuni esempi:

  • md5 (md5 (salt) + bcrypt (password))
  • scrypt (bcrypt (password + salt))
  • sha1 (md5 (scrypt (password + md5 (salt))))

Gli argomenti tipici contro questi vai come segue:

Non sei un crittografo! Non hai idea se questi hash siano più sicuri. Lascia fare agli esperti che sanno cosa stanno facendo. Questi non aggiungono ulteriore sicurezza.

Certo, non migliorano la funzione come hash (cioè rendono più difficile invertire o trovare collisioni ecc.), Ma sicuramente sicuramente non lo rendono peggio come hash? Se lo facessero, gli hacker sarebbero in grado di rieseguire l'hashing delle password con hash standard in questi hash stravaganti come ritengono opportuno e indebolire l'hash? Non lo compro.

Secondo argomento:

Principio di Kerckoffs: un sistema crittografico dovrebbe essere sicuro anche se tutto ciò che riguarda il sistema è noto.

D'accordo. Questa è fondamentalmente la motivazione per non memorizzare le tue password come testo in chiaro in primo luogo. Ma se la mia risposta alla prima critica è valida, questi stravaganti hash funzionano ancora come hash sicuri e il nostro sistema non infrange il principio di Kerckoffs più di quanto farebbe con un hash standard.

Ecco due possibili (e utili, per quanto posso vedere) vantaggi nell'usare un hash "stravagante" rispetto a un hash normale:

  1. Certo, il tuo sistema dovrebbe essere protetto se l'aggressore ha il codice sorgente, ma è molto probabile che il tuo aggressore non abbia accesso al tuo codice sorgente e probabilmente non sarà in grado di indovinare il tuo bizzarro hash, rendendo impossibile qualsiasi tentativo di forza bruta.
  2. (Questa è la vera motivazione dietro la mia domanda) BCrypt è pensato per essere sicuro, difficile per CPU e GPU (ottimo) ma può essere molto veloce con hardware specializzato. Si dice che SCrypt sia difficile da forzare su CPU, GPU e attualmente disponibili hardward specializzati, ma è più recente e non è considerato attendibile dalla comunità crittografica tanto quanto BCrypt a causa della mancanza di visibilità che ha avuto. Ma l'hash BCrypt (SCrypt (password + salt)) non ottiene il meglio da entrambi i mondi?

Apprezzo che la passione / rabbia dietro la maggior parte delle invettive contro questi hash fatti in casa deriva dalla mancanza di conoscenza del programmatore medio di ciò che rende un buon hashish e dalla preoccupazione che incoraggiare questo tipo l'hashing stravagante finirà inevitabilmente con hash deboli e inutili che entrano nel codice di produzione. Ma Se l'hash stravagante è costruito con cura a partire da hash solidi e affidabili, i guadagni in termini di sicurezza non sono molto preziosi e reali?


Aggiorna

Ho un sacco di buone risposte su questo, grazie. Quello che sembrava trascurare nelle mie ipotesi era che, sebbene la combinazione di hash non possa rendere più facile il crack della password originale e quindi il crack degli hash costituenti, la combinazione di due o più hash sicuri può: almeno in linea di principio - essere più debole di uno qualsiasi dei suoi hash interni a causa delle interazioni complesse e non studiate tra di loro. Significa che potrebbe essere possibile trovare qualche stringa che ha superato l'hash stravagante senza necessariamente rompere gli hash che la componevano.

Se il tuo obiettivo è solo quello di proteggerti da un utente malintenzionato senza accesso al tuo codice sorgente, allora [usando un peperoncino] (http://security.stackexchange.com/questions/21263/how-to-apply-a-pepper-correctly- to-bcrypt) (fondamentalmente un valore segreto hardcoded che si hash insieme alla password) sarebbe sufficiente e meno soggetto a errori rispetto alla creazione di una propria funzione hash.
perché non aggiungere un `sleep (15000);` dopo ogni hash? certo i benefici sono sconosciuti ma di certo non lo rende meno sicuro :)
Dieci risposte:
Polynomial
2013-04-01 16:32:59 UTC
view on stackexchange narkive permalink

Il fatto che tu debba porre questa domanda è la risposta stessa: non sai cosa c'è di sbagliato nell'impilare queste primitive, e quindi non puoi sapere quali vantaggi o ci sono punti deboli.

Facciamo alcune analisi su ciascuno degli esempi che hai fornito:

md5 (md5 (salt) + bcrypt (password))

Vedo alcuni problemi qui. Il primo è che stai MD5'ing il sale. Che vantaggio offre questo? Nessuna. Aggiunge complessità e il sale è semplicemente pensato per essere unico per prevenire collisioni di password e attacchi di pre-calcolo (ad es. Tabella arcobaleno). L'uso di MD5 qui non ha alcun senso e potrebbe effettivamente indebolire lo schema poiché MD5 ha conosciuto collisioni banali. Pertanto, esiste una piccola possibilità che l'introduzione di MD5 qui possa significare che due sali unici producono lo stesso hash MD5, risultando in un sale effettivamente duplicato. Non va bene.

Successivamente, usi bcrypt sulla password. Ok. Ebbene, la maggior parte delle implementazioni di bcrypt richiede un salt internamente, quindi questo è già tecnicamente non valido. Supponiamo che tu lo sappia e che volessi dire bcrypt (md5 (salt), password) . Questa parte sta ancora cadendo nella debolezza che ho descritto sopra, ma non è troppo malandata: rimuovi l'MD5 ed è un uso standard di bcrypt.

Infine, MD5 il tutto. Perché stai facendo questo? Qual è lo scopo? Che vantaggio porta? Per quanto posso vedere, non c'è alcun vantaggio. Sul lato negativo, aggiunge più complessità. Poiché la maggior parte delle implementazioni di bcrypt usa la notazione $ 2a $ rounds $ salt $ hash , dovrai scrivere del codice per analizzarlo in modo da poter estrarre la parte hash e memorizzare il resto separatamente. Avrai anche bisogno di un'implementazione MD5, che non era necessaria.

Quindi, in termini di impronta del codice per potenziali vettori di attacco, sei passato da una semplice implementazione di bcrypt, a un'implementazione di bcrypt con codice di analisi personalizzato e implementazione MD5 e un po 'di codice collante per incollare tutto insieme. Per zero vantaggi e una potenziale vulnerabilità nella gestione del sale.

Avanti:

scrypt (bcrypt (password + salt))

Questo non è poi così male, ma ancora una volta hai bisogno di un po 'di codice per analizzare i risultati di bcrypt in hash e salt / round count separatamente. In questo caso immagino che ci sia un leggero vantaggio, perché bcrypt e scrypt funzionano in modi diversi per più o meno lo stesso obiettivo, il che renderebbe un po 'più difficile per un hacker estremamente ben finanziato per creare ASIC personalizzati per rompere il tuo schema. Ma è davvero necessario? Stai davvero andando a colpire una situazione in cui uno stato nazione dedicherà qualche milione di dollari solo per rompere il tuo hash? E, se mai si presentasse questo caso, infastidirà davvero l'attaccante dover spendere qualche milione in più per raddoppiare il numero di chip?

Un altro potenziale problema con la combinazione di bcrypt e scrypt in questo modo è che c'è stato molto poco studio su come i due interagiscono. Pertanto, non sappiamo se ci sono casi strani che possono causare problemi. Come esempio più ovvio, prendi l'unico time pad. Calcoliamo c = m ^ k per un messaggio m e una chiave altrettanto lunga perfettamente casuale k e otteniamo una sicurezza perfetta. Quindi facciamolo due volte , per una sicurezza ancora maggiore! Questo ci dà c = m ^ k ^ k ... oh, aspetta, questo ci dà solo m . Quindi, poiché non ci siamo presi il tempo per capire correttamente come funzionavano le parti interne del sistema, ci siamo ritrovati con una vera vulnerabilità di sicurezza. Ovviamente è più complicato nel caso dei KDF, ma vale lo stesso principio.

E infine:

sha1 (md5 (scrypt (password + md5 (salt))) )

Ancora una volta ci stiamo imbattendo nel problema del sale con MD5. Sono anche incuriosito dal fatto che MD5 abbia l'hash SHA1. Quale possibile vantaggio potrebbe avere, se stai già utilizzando un KDF lento come scrypt? I pochi nanosecondi necessari per calcolare quegli hash impallidiscono rispetto alle centinaia di millisecondi necessari per calcolare lo scrypt digest della password. Stai aggiungendo complessità per un livello di "sicurezza" assolutamente irrilevante, che è sempre una cosa negativa. Ogni riga di codice che scrivi è una potenziale vulnerabilità.


Ora ricorda quel punto che ho fatto all'inizio della mia risposta. Se, in qualsiasi momento di questa risposta, hai pensato "oh sì, non ci ho pensato", allora il mio punto è dimostrato.

Ti stai imbattendo in quello che descriverei come La falsa massima di Dave:

Se aggiungo più cose crittografiche, sarà più sicuro.

Questo è un tratto comune tra sviluppatori, e una volta ci credevo anch'io. Va di pari passo con la negazione di altri principi, come il Principio di Kerckhoff. In definitiva, devi capire e accettare che l'oscurità non è un parapetto di sicurezza; è una stampella per criptovalute deboli. Se la tua crittografia è forte, non ha bisogno di stampelle.

Bella risposta. Non avevo davvero pensato al primo e all'ultimo esempio di hash impilato. Hanno rovinato un po 'la mia discussione senza motivo. Ero più interessato all'hash bcrypt - scrypt e se questo potesse * possibilmente * essere più debole di entrambi gli scrypt / bcrypt da soli.
L'interazione tra i due è indefinita, perché nessuno l'ha studiata. La combinazione dei due * potrebbe * fornire maggiore sicurezza, ma * potrebbe * portare anche a interazioni insolite tra le parti interne di quegli hash. Un buon esempio di questo è l'unico time pad. Il calcolo di "c = m ^ k" fornisce un perfetto livello di sicurezza quando "k" è veramente casuale e sconosciuto all'attaccante. Quindi facciamolo due volte, per maggiore sicurezza! Quindi finiamo con "c = m ^ k ^ k", che risulta in "m". Oh, whoops. Ovviamente le interazioni sono più complesse negli hash, ma il principio è ancora valido.
Il punto è che, poiché non sappiamo quali potenziali problemi potrebbero esistere, perché non seguire il percorso sicuro noto e usare semplicemente scrypt con un fattore di lavoro dignitoso? È più che abbastanza sicuro per quasi tutti gli scopi.
@Polynomial +1 Ottima risposta. Tuttavia non ero convinto della parte bcrypt / scrypt della tua risposta fino a quando non ho letto il tuo commento sui one-time pad. Potrei considerare di aggiungere quel commento alla tua risposta.
@Phil Fatto. Si spera che abbia senso.
"Un altro potenziale problema con la combinazione di bcrypt e scrypt in questo modo è che sono stati condotti pochissimi studi sul modo in cui i due interagiscono. In quanto tale, non sappiamo se ci sono casi strani che possono causare problemi. Come esempio più ovvio, prendiamo l'unico time pad. Calcoliamo c = m ^ k per un messaggio me una chiave k perfettamente casuale, ugualmente lunga, e otteniamo una sicurezza perfetta. Quindi facciamolo due volte, per una sicurezza ancora maggiore! " Lo stai facendo male. La roba `bcrypt (scrypt (x))` è ok mentre `xor (xor (x, k), k)` non lo è perché un ulteriore `bcrypt` è qualcosa che anche un attaccante potrebbe fare.
@thejh Era un esempio di come l'ignoranza delle parti interne di un'operazione possa portare a vulnerabilità di sicurezza. Non voleva essere un'analogia diretta, ecco perché ho detto "Ovviamente è più complicato nel caso dei KDF, ma vale lo stesso principio".
Ancora non vedo perché la cosa scrypt (bcrypt (x)) potrebbe essere un problema. Se i due interagiscono in modo strano, il solo utilizzo di bcrypt non lo rende più sicuro: un utente malintenzionato può semplicemente scrypt () ciò che hai bcrypt () 'd. Inoltre, se qualcuno trova un modo più intelligente per indovinare il testo in chiaro originale per un algoritmo di hashing, probabilmente non avrà contemporaneamente un modo più veloce per l'altro algoritmo. Mettiamo che le persone pensassero legittimamente che ROT13 fosse un buon meccanismo di hashing. Se usassi ROT13 (bcrypt (x)), non starei ancora meglio quando le persone "crackano" ROT13?
Il problema principale è che devi introdurre più codice per analizzare l'output codificato di scrypt / bcrypt in modo che il conteggio del sale e del round possa essere memorizzato separatamente. Inoltre, in realtà non offre alcuna maggiore sicurezza: scrypt è più che sufficiente per il 99,9% delle situazioni.
Usare scrypt e bcrypt insieme ha il problema che entrambi richiedono tempo per essere eseguiti: probabilmente finirai per dimezzare il numero di round su ciascuno per compensare il fatto di dover eseguire entrambi, il che è più probabile che sia insicuro di uno scrypt "completo" sopra un bcrypt "completo" è.
@Brilliand: Gli attaccanti troveranno quasi certamente modi per velocizzare entrambi gli algoritmi almeno in qualche modo, probabilmente in misura diversa. Se si scopre che gli attaccanti trovano un aumento di 100: 1 per un algoritmo e 2: 1 per l'altro, gli attaccanti otterrebbero un aumento di circa 4: 1 contro un sistema che utilizzava ciascun algoritmo per la metà dei round che avrebbero potuto utilizzare nel assenza dell'altro. A meno che non si sappia con quale sistema gli attaccanti avrebbero "migliore fortuna", la copertura delle scommesse non sembra irragionevole.
@Polynomial: Ho pubblicato una risposta semplificata (una specie di riepilogo).Non sono sicuro che la mia logica sia corretta, quindi se hai pochi minuti, potresti controllarla / modificarla per favore?Credo possa essere utile.Grazie in anticipo!
@root: Questo darà loro qualcosa di simile che scrypt (bcrypt (what_attacker_has)) = scrypt (bcrypt (real_password)), ma non necessariamente tale che bcrypt (what_attacker_has) = scrypt (real_password).
@Polynomial, `m ^ k ^ k` non è una buona analogia.Che mi dici di "m ^ k ^ k2"?Non vedo come sarebbe ** meno ** sicuro.
@Ricky, ??Non credo che nessuno abbia capito quello che stai cercando di dire.
@Brilliand, Dividere la percentuale di hash su diversi tipi di algoritmi è in realtà un vantaggio a causa delle ** economie di scala **.Un utente malintenzionato che potrebbe produrre interruttori ottimizzati per bcrypt potrebbe non essere allo stesso tempo in grado di produrre interruttori ottimizzati per scrypt.La stessa logica si applica a tutti gli hash di razze diverse.
Un problema più grande è che `sha1 (md5 (m))` per qualsiasi valore di `m` riduce i possibili risultati a 128 bit, nonostante SHA-1 fornisca un digest a 160 bit.Anche se probabilmente non è un grosso problema perché 128 è ancora abbondante, stai riducendo inutilmente la dimensione del digest.Considera un esempio estremo, dove hai `sha1 (crc8 (m))`.Nonostante un digest SHA-1 sia a 128 bit, ci saranno solo 256 possibili risultati a causa del CRC a 8 bit nel mezzo.Creando un collo di bottiglia, riduci la sicurezza limitando la dimensione della chiave.
https://crypto.stackexchange.com/questions/59583/if-and-why-is-it-bad-to-scrypt-a-bcrypted-password/59588#59588
E se usassi solo la stringa hash combinata?
@SolomonUcko Quindi diventa altamente vulnerabile agli attacchi di preimage parziali.
Adam Caudill
2013-04-01 07:03:56 UTC
view on stackexchange narkive permalink

Le primitive crittografiche possono essere impilate in modo sicuro e aumentare la sicurezza se, e solo se, conosci le primitive abbastanza bene da comprendere le loro debolezze e come interagiscono queste debolezze. Se non li conosci o non capisci i dettagli, beh, è ​​così che ottieni il protocollo di Dave.

Il problema è che pochissime persone li conoscono tutti abbastanza bene per giudicare se una certa combinazione è sicura. Ecco perché deve essere qualcosa che viene pubblicato e rivisto, se non è stato rivisto non hai modo di sapere se è forte come scrypt o se è più vicino a CRC32.

Quindi, se non sei un esperto, è del tutto possibile che tu abbia qualcosa di più debole della primitiva più debole che hai usato (vedi il protocollo di Dave) e non lo sapresti. O almeno non lo sapresti fino a quando non viene decifrato: trovare le password dei tuoi utenti su Pastebin non è proprio il modo ideale per determinare che lo schema è difettoso.

Sono d'accordo che un certo grado di oscurità può aiuto da una prospettiva di difesa in profondità, ma il sistema sottostante deve essere sicuro.

Tra scrypt , bcrypt e PBDKF2 - almeno uno di essi sarà supportato praticamente su tutte le piattaforme. Questi sono noti e ben testati: offrono diversi livelli di protezione, ma sono comunque molto più sicuri di un bizzarro raggruppamento di md5 e sha1 .

Penso che lo stacking di md5 e sha1 sia stato un cattivo esempio, non lo userei mai ed era solo per l'illustrazione. Sono particolarmente interessato allo stack bcrypt-scrypt. Continuo a non capire come potrebbe indebolire l'hashish? Come ho detto, è un passo che potrebbe essere fatto da un hacker se lo volesse comunque, quindi se indebolisce l'hash, allora è un grosso problema anche se non lo faccio per loro!
@GeorgePowell: Un hacker non è interessato solo a recuperare le password in chiaro originali. Potrebbe anche essere interessato a trovare collisioni. È possibile aumentare la quantità di collisioni concatenando queste funzioni insieme.
Potresti spiegare perché, se un hacker ha accesso al database, sta tentando di trovare le collisioni? Inoltre, sicuramente il numero di collisioni create da una funzione hash è una funzione della sua qualità? Se l'hashing di un hash si traduce in più collisioni, suggerirei che la funzione hash è scarsa sin dall'inizio.
Thomas Pornin
2013-04-01 22:58:30 UTC
view on stackexchange narkive permalink

Per la tua domanda specifica sulla combinazione di scrypt e bcrypt, ricorda che queste funzioni hanno un costo configurabile e vuoi aumentare quel costo il più possibile, mantenendolo tollerabile per il tuo utilizzo specifico. Ad esempio, se puoi utilizzare bcrypt con un massimo di X iterazioni (oltre le quali è troppo costoso per il tuo server e il tuo numero medio di connessioni utente al secondo), o scrypt con un massimo di Y iterazioni, quindi non puoi usare scrypt (bcrypt) con X iterazioni per bcrypt poi Y iterazioni per scrypt: questo andrà oltre il budget della CPU.

Quindi, se si sovrappongono scrypt e bcrypt, è necessario utilizzarli entrambi con meno iterazioni di quanto si sarebbe potuto fare con uno solo. Non "ottieni il meglio di entrambi i mondi" semplicemente mettendoli insieme. In effetti, il meglio che puoi sperare è una sorta di media tra i due. E questo ha il prezzo di un codice più complesso, qualcosa che è intrinsecamente negativo quando si parla di sicurezza (o, per quella materia, manutenibilità).

È probabile che la maggior parte degli algoritmi diventi più veloce nel tempo, anche se non necessariamente in quantità uguali. Supponiamo che ci sia una probabilità dell'1% che il metodo X venga accelerato di 100 volte e una probabilità del 10% che venga accelerato di due volte; allo stesso modo per il metodo Y. A meno che non mi manchi qualcosa, penserei che eseguire entrambi gli algoritmi a metà intensità significherebbe che un enorme aumento della velocità sarebbe possibile per il composito solo se fosse possibile per * entrambi * gli algoritmi costituenti.
Sì, un altro problema sono le economie di scala.Menzionato qui: https://security.stackexchange.com/questions/33531/why-improvising-your-own-hash-function-out-of-existing-hash-functions-is-so-bad?rq=1#comment254238_33550
Stephen Touset
2013-04-01 08:10:49 UTC
view on stackexchange narkive permalink

Oltre alla risposta di Adam, vorrei anche menzionare che ogni volta che usi la crittografia, dovresti avere una ragione forte e inevitabile per farlo. Negli esempi precedenti, questo non esiste.

  md5 (md5 (salt) + bcrypt (password)) scrypt (bcrypt (password + salt))  

Gli algoritmi bcrypt e scrypt sono già abbastanza potenti e considerati effettivamente indistruttibili. Che problema stai cercando di risolvere? E perché credi che combinare i loro risultati (in particolare con md5 ) lo risolverà? Nella migliore delle ipotesi, probabilmente hai semplicemente ridotto la difficoltà di crackare la password a quella dell'hash più debole, piuttosto che migliorare effettivamente la sicurezza. E lo scenario peggiore è spaventosamente indefinito.

  md5 (sha1 (md5 (md5 (password) + sha1 (password + salt)) + password))  

Questa soluzione è anche peggiore. Implementa manualmente uno schema di hashing ripetuto, ma senza giri sufficienti per imporre effettivamente un fattore di lavoro significativo agli aggressori.

In poche parole, il problema è che:

  • tu " stai facendo il giro della crittografia senza avere effettivamente un problema che deve essere risolto
  • hai notevolmente aumentato la probabilità di introdurre difetti nella tua implementazione
  • probabilmente hai diminuito la sicurezza ai più deboli dei algoritmi di hashing e
  • hai introdotto uno scenario peggiore sconosciuto in cui non esisteva nessuno
Il "problema che sto cercando di risolvere" oi vantaggi di risolverli sono stati affrontati alla fine della domanda. E ancora non capisco come uno stack di hash come sha1 (md5 (bcrypt ())) possa essere più debole di bcrypt! Per favore, spiega, se mettere md5 in cima a bcrypt lo ha reso più debole, allora perché diavolo gli hacker non lo fanno da soli una volta ottenute le password bcryt-ed?
@GeorgePowell Il tuo schema `sha1 (md5 (bcrypt ())) * non ha senso *. Cosa offre che bcrypt da solo non fa? Se stai cercando maggiore sicurezza in bcrypt, perché non aumentare semplicemente il fattore lavoro o passare a scrypt? Abusare di altre primitive hash, in particolare quelle principalmente rotte come MD5, per un vantaggio indefinito e minuscolo (che può * effettivamente * essere un danno) non è intelligente e può solo fornire una maggiore complessità.
Sono d'accordo che non ha senso, hai ragione. Non produce un hashish migliore. Ma non capisco come potrebbe renderlo più debole? Anche se avessi battuto completamente gli hash md5 e sha1, rimarrai comunque con tutti i punti di forza di bcrypt? O mi sbaglio completamente qui?
Il problema di sicurezza non è realmente crittografico. Devi scrivere righe di codice per produrre questa implementazione e ogni riga che scrivi porta potenziali vulnerabilità. Anche cose sottili come il modo in cui Unicode viene gestito su alcune macchine possono essere catastrofiche dal punto di vista della sicurezza. Mantienilo semplice, mantieni l'implementazione pulita da inutili schifezze e sarai più sicuro.
@GeorgePowell Non li aiuta. Immagina che esista una funzione hash con uno spazio di output di un singolo byte. Ovviamente è * banale * per un attaccante forzare brute le nostre password se lo usiamo in qualsiasi momento per calcolare digest (anche se in seguito lo passiamo a qualcosa come `bcrypt`). Ma il fatto che questo hash debole esista non consente a un attaccante di usarlo contro di noi, perché * non lo stiamo * usando.
@GeorgePowell Inoltre, il "problema" che stai cercando di risolvere in realtà non esiste. È puramente immaginario. Se esistesse, i crittografi professionisti si arrovellerebbero come matti per fornire una soluzione permanente. La tua apparente convinzione che 1) esiste un problema pratico, 2) non esiste una soluzione pubblicata, e 3) la "soluzione" è banale si accompagna all'asserzione implicita che i crittografi professionisti sono stupidi e / o pigri. Altrimenti avrebbero già trovato una soluzione, giusto?
Marcks Thomas
2013-04-01 15:54:51 UTC
view on stackexchange narkive permalink

Se applichi operazioni non sicure a un algoritmo sicuro, puoi sicuramente interrompere la funzione di hashing. La tua nuova funzione potrebbe anche essere di gran lunga peggiore dell'anello più debole.

Perché gli aggressori non lo usano per interrompere le funzioni protette? Non li aiuta. Ad esempio, se sovrascrivo i primi 440 bit di una password memorizzata in modo sicuro utilizzando bcrypt con zero, posso facilmente trovare una password corrispondente con la forza bruta, ma quella password funzionerà solo sul mio terribile algoritmo. Un'implementazione sana probabilmente lo rifiuterebbe.

L'azzeramento di grosse porzioni di un hash è chiaramente un male, ma anche le operazioni sicure possono essere combinate in qualcosa di pericoloso. L'aggiunta di due numeri (modulo n per garantire una lunghezza costante) è "sicura". Generalmente, nessuna entropia viene persa. Tuttavia, h (x) + h (x) mod n riduce la qualità dell'hash h (x) di un bit, poiché il risultato è sempre pari. L'operatore altrettanto sicuro XOR fa anche peggio, poiché h (x) XOR h (x) restituisce sempre zero.

Queste insidie ​​sono abbastanza ovvie, ma non tutte lo sono. Tieni presente che, come sempre, è banale inventare uno schema abbastanza buono da non trovare punti deboli da solo, ma molto difficile inventarne uno dove nessun altro può.

Buona risposta, penso di aver capito il succo: gli hash stravaganti * potrebbero * rendere più facile trovare una corrispondenza con la forza bruta ma non potrebbero rendere più facile trovare la password originale che è stata utilizzata. Questo è il motivo per cui gli hacker non hanno motivo di applicare da soli l'hash più debole. Il cracking dell'hash impilato non implica il cracking degli hash interni.
ponsfonze
2013-04-01 12:36:53 UTC
view on stackexchange narkive permalink

Le funzioni hash vengono create dai crittografi e distrutte dai crittografi. Ci sono molte funzioni hash forti e funzioni deboli ancora in uso oggi. I programmatori dovrebbero fidarsi dei crittografi e della funzione hash. Se ci fosse mai una vulnerabilità nella funzione hash, allora ne sentiresti sicuramente parlare su Internet o tramite colleghi e quindi i crittografi faranno sicuramente un'indagine approfondita. Con qualsiasi algoritmo di hash sicuro, è noto che l'unico punto debole potrebbe essere un attacco bruteforce.

La combinazione di funzioni hash non aggiunge quasi nessuna sicurezza extra e qualsiasi cosa tu voglia aggiungere, probabilmente è già implementata nella funzione.

Salare una password è ottimo per ridurre l'efficacia contro le tabelle arcobaleno in modo tale che una password non possa essere semplicemente "cercata". Sia che abbiate hash una funzione due volte o cambiate la funzione hash, essenzialmente sta saltando la password. E la maggior parte delle funzioni include un metodo semplice per il sale, quindi non è davvero necessario implementarlo.

Diciamo che voglio creare il mio hash sicuro perché lo fanno tutti. E poiché non sono un crittografo, ne avrò bisogno "veramente" sicuro, perché ovviamente ogni programmatore sa come creare un hash sicuro invece di usare quelli sicuri già creati. Quindi creo la mia subdola funzione hash, mod10 (md5 (sha1 (bcrypt (password + salt)))).

Come puoi vedere dalla mia funzione hash, è davvero sicura perché ne uso tante diverse cose in esso. Ovviamente in questo stupido esempio, è facile vedere che ci saranno solo 10 diversi output possibili. Ma semplicemente utilizzando una singola funzione hash sicura, l'avrebbe completamente evitato.

Certo, il tuo sistema dovrebbe essere sicuro se l'aggressore ha il codice sorgente, ma è molto probabile che il tuo l'attaccante non avrà accesso al tuo codice sorgente e probabilmente non sarà in grado di indovinare il tuo stravagante hash, rendendo impossibile qualsiasi tentativo di forza bruta

Quindi supponiamo che un utente malintenzionato abbia acquisito la tabella del database che contiene gli hash. Presumo che sia molto probabile che un utente malintenzionato possa ottenere anche i file della pagina Web. I tuoi sistemi che eseguono questi servizi potrebbero essere lo stesso exploit che ti ha permesso di prendere il database. Un server di database è configurato in modo che il pubblico non possa accedervi direttamente. D'altra parte, il tuo server web contenente il tuo codice è in prima linea.

Eric G
2013-04-01 09:04:30 UTC
view on stackexchange narkive permalink

Ogni volta che aumenti la complessità di un algoritmo o addirittura aggiungi più righe di codice, aumenti i punti di errore nella tua applicazione. Potrebbero esserci conseguenze indesiderate della combinazione di algoritmi. Ciò può portare a determinati tell o altri segni che possono effettivamente indebolire la forza crittografica del sistema.

Più librerie usi nella tua applicazione, maggiore è il rischio per la tua applicazione in generale. Se viene rilevato un difetto in un'implementazione che consente una debolezza, l'esecuzione di codice, ecc., La tua applicazione è vulnerabile. Se per fortuna ti è capitato di selezionare un altro algoritmo che non è stato attaccato, sei al sicuro per il momento (ovviamente potresti anche essere dalla parte sfortunata della fortuna).

Ricorda BACIO : mantienilo semplice, stupido, altrimenti potresti perderti nella complessità.

emory
2013-04-02 05:05:12 UTC
view on stackexchange narkive permalink

Non sono d'accordo con un intero gruppo di persone che sono più intelligenti di me e più esperte in sicurezza di me. Quindi probabilmente mi sbaglio.

Improvvisare la tua funzione hash è una buona idea, se lo fai bene. Segui questi 3 semplici passaggi.

  1. Identifica un punto debole o un difetto nelle funzioni hash esistenti.
  2. Improvvisa la tua funzione hash che non ha questo difetto.
  3. Verifica che la tua funzione hash improvvisata abbia tutti i punti di forza delle funzioni hash esistenti.

Dopo aver completato il passaggio 3, saresti un pazzo a non usare la tua funzione hash improvvisata.

Il problema è che * non puoi * completare il passaggio 3. Nessuno al mondo è in grado di determinare unilateralmente che un nuovo algoritmo di hash è forte. Questo è il motivo per cui, al fine di ottenere l'accettazione, i nuovi algoritmi candidati vengono sottoposti a massicci concorsi pluriennali sottoposti a revisione paritaria e sottoposti a un'eccezionale quantità di controllo. Semplicemente non puoi sapere se un algoritmo è sicuro nel vuoto.
@Xander, Non riesco a completare nessuno dei passaggi. Quindi per me non improvviso. Mentre il passaggio 3 è probabilmente il più importante, il passaggio 1 è il più semplice. Se non riesci almeno a identificare un problema con una funzione hash sicura esistente, allora perché stai sprecando il tuo tempo improvvisando una nuova funzione hash.
user3083447
2016-12-13 20:55:07 UTC
view on stackexchange narkive permalink

Quando si concatenano diverse funzioni hash perché si è preoccupati di quella è vitale che si riapplichi il sale prima di applicare l'algoritmo di hashing successivo, quindi qualsiasi punto debole di collisione in uno degli algoritmi non contaminerà la seconda funzione hash che sei utilizzando:

scrypt (bcrypt (password + salt) + salt)

Ma penso che scrypt sia una tecnica consolidata ora, Argon 2i ha vinto la competizione di hashing delle password e si crede che lo sia più sicuro e bcrypt esiste da molto tempo e si è dimostrato sicuro contro banali bypass.

Pertanto quanto segue avrebbe più senso e combinerebbe la forza di argon 2i, ma ricadrebbe su bcrypt se un futuro attaccante mostrasse come rompere banalmente l'argon 2i, cosa che al momento si pensa sia difficile:

bcrypt (Argon2i (password + salt) + salt)

Ma tu sei meno probabile commettere un errore se lo fai semplicemente:

scrypt (password + salt) Orbcrypt (password + salt)

Ricorda, la maggior parte delle violazioni sono dovute all'erro umano r nel codice, è molto meglio mantenerlo semplice e rivedere completamente il codice con analisi statiche dinamiche e revisori di codice umano, per assicurarsi che nessun attacco sql injection sfugga (ricorda sempre di parametrizzare le query del database!)

lepe
2016-04-13 07:06:44 UTC
view on stackexchange narkive permalink

Ho imparato molto con questo thread, quindi ho pensato in modo da comprendere facilmente il possibile risultato quando si combinano metodi diversi (ovviamente, non si adatta a tutti i casi):

[W = debole, S = forte]:

  Formula | Esempio --------------- | ----------------- W (W) = W | md5 (sha1 (pwd)) W (S) = W | md5 (bcrypt (pwd)) S (W) = W | bcrypt (md5 (pwd)) S (S) = S- | bcrypt (scrypt (pwd)) // la loro interazione è sconosciuta W + S = W | md5 (pwd) + brcypt (pwd) S + S = W | bcrypt (pwd) + scrypt (pwd) W '+ S "= S | md5 (pwd1) + brcypt (pwd2) // pwd1! = pwd2S' + S" = 2S | bcrypt (pwd1) + scrypt (pwd2) // pwd1! = pwd2SUBSTR (W) = W | substr (md5 (pwd), n); // Più corta la stringa, più deboleSUBSTR (S) = S- | substr (bcrypt (pwd), n); // Più corta la stringa, più debole S + x = S + | bcrypt (pwd) + x // x = Variabile str. non correlato a pwdS (S + x) = S- | bcrypt (scrypt (pwd) + x) // x = Variable str. non correlato a pwdROT13 (S) = S | ROT13 (bcrypt (pwd)) 

Quello che voglio ottenere qui è mostrare in modo semplice che quelle combinazioni non aggiungeranno ulteriore sicurezza nella maggior parte dei casi (quindi la complessità aggiunta è non degno).

È impossibile dire una cosa così generale come "S (S) = S-".Come ha spiegato Polynomial in un commento sopra, la ripetizione di una forte funzione di hashing può in linea di principio risultare in un hash completamente inutile.Su cosa si basano queste "formule"?
@GeorgePowell: Sì, "S (S)" potrebbe portare a un comportamento imprevisto, che potrebbe potenzialmente risultare in un hash inutile.Questo è il motivo per cui è contrassegnato: "S-", il che significa che sarà meno forte della sola "S", quindi non è raccomandato.Poiché non stiamo specificando gli algoritmi effettivi, non possiamo essere sicuri al 100% che produrrà hash inutili, ma dovrebbe essere evitato a causa di tale rischio.Queste "Formule" non hanno in alcun modo basi scientifiche e sono solo il mio tentativo di rappresentare tali interazioni in modo semplice in modo che chiunque cerchi di "gestirle" possa avere un'idea di cosa aspettarsi ed evitare il loro utilizzo.
@lepe, `W (S) = W`?Sei sicuro?Vedi https://security.stackexchange.com/questions/33531/why-improvising-your-own-hash-function-out-of-existing-hash-functions-is-so-bad?rq=1#comment52264_33550
@Pacerier: Un punto da analizzare è la "probabilità di collisione".Se usi MD5 per eseguire l'hashing di un hash bcrypt, aumenti le possibilità di collisione e quindi ne riduci la forza.Inoltre, se l'hash MD5 è compromesso, forzare direttamente l'hash MD5 potrebbe essere molto più veloce, rimuovendo "S" dalla formula (a seconda dell'implementazione che potrebbe essere un grosso problema).Un altro punto è che se l'algoritmo W ha un difetto di sicurezza, può rendere difettoso anche il W (S).Per questi motivi, W (S) non dovrebbe mai essere considerato S o S +.È meglio usare S da solo per evitare di aggiungere complessità e rischi inutili.
@lepe, ** 1) ** Sicuramente potresti forzare "W", ma forzare "W" ti dà "S (password)", non la password stessa.In altre parole, dopo aver forzato brute a "W" sei ** tornato al punto di partenza **.Vedi il link al commento di Root sopra.** 2) ** Successivamente, se l'algoritmo `W` ha un difetto di sicurezza, ** non può ** rendere` W (S) `difettoso.[cont]
[cont] Perché se "W (S)" è difettoso, allora "S" non sarebbe più chiamato "S" poiché "S" si direbbe che è rotto e non è più un hash ** S ** trong.http://en.wikipedia.org/wiki/Self-refuting_idea.In altre parole, prima di essere hackerati, qualcuno avrebbe fatto notizia nel mondo rompendo la "S".Anche se è certamente vero che c'è una possibilità che il mondo abbia cracker con più esperienza rispetto ai ricercatori bianchi e ai crittoanalisti, consentendo alla conoscenza di aver rotto la "S" di circolare nel mercato nero per un tempo più lungo prima che sia pubblicamente noto.
Buon tavolo tranne ROT13 (S) = S. Consiglio ad alcune persone che temono davvero la scheda ASIC di serie di fare XOR (S, chiave) dove la chiave è memorizzata altrove, quindi ...
@Pacerior: Ho visto alcuni casi in cui W era così grave che il bruting W (S) era fattibile.Suggerimento: se W ha 64 bit di entropia, in media 1 << 63 prove saranno sufficienti.
@Pacerier: Ho cambiato ROT13 (S) = S come suggerito.


Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 3.0 con cui è distribuito.
Loading...