Hashing lento senza sale?

1

Sto provando a progettare uno schema di sicurezza che prevede un segreto condiviso ma non è una situazione tradizionale per la password dell'account. Il server memorizzerebbe un insieme di "chiavi", ognuna delle quali ha un blob di dati ad essa associato. Per consentire a chiunque di accedere ai dati per una determinata chiave, tutto ciò che devono sapere è il nome in chiaro della chiave. Quindi se Alice crea i dati usando "ananas" come chiave, Bob può chiedere al server i dati per la chiave "ananas" e il server restituirà i dati.

È del tutto intenzionale che Bob possa condividere la parola segreta ad altre persone o che le persone possano indovinare casualmente "ananas" e ottenere accidentalmente i dati. Voglio solo evitare che qualcuno sia in grado di forzare bruscamente un numero molto grande di tasti per parole di dizionario comuni facilmente. Vorrei che nessuno dei dati in chiaro venisse mai inviato al server, in modo che le persone che eseguono il server non possano spiare i dati dell'utente o nemmeno sapere quali siano le chiavi in chiaro. E idealmente se il server fosse compromesso, ci vorrebbe molto tempo per forzare bruscamente ciascuna delle chiavi in chiaro e / o decrittografare i dati corrispondenti.

La mia idea su come questo potrebbe funzionare, è che se Alice vuole creare nuovi dati, il loro cliente prende la chiave "ananas" ed esegue su di esso un algoritmo hash molto lento, creando eventualmente il corrispondente codice hash per l'ananas. Quindi il loro client crittografa il pacchetto dati con "ananas" usando anche una sorta di metodo di crittografia che è difficile da forzare. Alice avrebbe quindi inviato entrambi al server, il che avrebbe verificato che l'hash non esistesse già e quindi memorizzasse la coppia di hash / dati. Più tardi, Bob potrebbe ripetere lo stesso processo di creazione di un codice hash per ananas, quindi chiedere al server i dati per quell'hash e infine decrittografare i dati restituiti usando l'ananas come chiave. Il processo di creazione dell'hash iniziale sarebbe lento, ma sia Alice che Bob potrebbero memorizzarlo localmente nel proprio client in modo da poterlo fare solo una volta per chiave.

C'è un modo migliore per farlo? Ci sono algoritmi di hash lenti che non implicano l'uso di un salt, il che impedirebbe ad Alice e Bob di capire lo stesso codice hash sicuro senza comunicare tra loro? C'è un modo per usare un salt ma usare ancora questo metodo generale dove il server non vede mai alcun testo in chiaro? Ci sono problemi di sicurezza con questo tipo di schema che non sto considerando?

    
posta Chris Graham 18.09.2018 - 18:40
fonte

1 risposta

3

Funzioni derivate chiave

Ciò che stai descrivendo non è in realtà diverso dalle funzioni di derivazione delle chiavi (KDF) già utilizzate in molte codifiche / password contesti di hashing. Un sacco di KDF hanno un parametro configurabile cost che può consentire di aumentare o diminuire il "Tempo CPU" totale (sto semplificando) necessario per generare la chiave effettiva dalla password. In questo caso ciò che chiamate key (cioè "ananas") sarebbe effettivamente una password che viene eseguita attraverso un KDF per generare una chiave cifrografica, che viene quindi utilizzata per la crittografia / decrittografia dei dati. Non dovrai mai inviare la password al server, solo la chiave generata, che viene sempre creata utilizzando KDF sul lato client.

Fattori di costo

Questo ultimo bit (generando il lato client chiave) sarebbe importante, perché per quello che stai parlando il fattore costo dovrebbe essere molto alto. Potrebbe essere un dettaglio che ti manca. L'unico modo per consentire alle persone di condividere una password e persino di indovinare le password, ma non essere in grado di forzare bruscamente le password casuali, è se il KDF è molto lento. Normalmente il parametro di costo è sintonizzato in modo che il tempo di generare la chiave su hardware "buono" sia, ad esempio, di 0,2 secondi (sto finendo di semplificare e saltare molti dettagli a titolo di esempio). Il motivo per cui scegli una scala temporale di ~ 0,2 secondi per la generazione di chiavi è bilanciare il desiderio di rendere la forza bruta costosa, ma anche fare in modo che il tuo sistema possa effettivamente eseguire le operazioni necessarie nel tempo che gli utenti sono disposti ad aspettare (es. nessuno vuole aspettare 30 secondi ogni volta che accedono).

Il problema

Tuttavia, anche se un utente malintenzionato può controllare solo una "password" al secondo, ci sono ancora 86400 secondi al giorno, il che significa che puoi passare attraverso l'intero dizionario inglese di oxford (~ 170.000 parole) in pochi giorni . Di conseguenza, per impedire a qualcuno di forzare brutalmente le parole del dizionario comune, si sta parlando di un processo di generazione della chiave che dovrebbe richiedere almeno alcuni minuti, e dubito che ciò fermerebbe un attaccante dedicato (specialmente se hanno hardware di fascia alta in grado di eseguire KDF in meno tempo). Se lo fai però, ciò significa che i tuoi utenti legittimi dovranno anche aspettare quegli stessi minuti prima che possano ottenere risultati dal tuo sistema. Dopo tutto, non c'è modo di distinguere tra un utente legittimo del tuo sistema e un aggressore, quindi l'unico modo per rallentare gli attaccanti è rallentare tutti . Quindi, per fare ciò che vuoi fare devi rallentare il tuo KDF in modo che ci voglia un po 'di tempo "lungo" per essere eseguito, ma è del tutto possibile che il livello di "lentezza" di cui hai bisogno per raggiungere il tuo livello Il desiderio (cioè l'interruzione della forza bruta delle parole comuni del dizionario) sarà così lento che i tuoi utenti non sono disposti ad aspettare che il tuo sistema faccia il suo esempio. In definitiva, trovare l'equilibrio tra usabilità e sicurezza spetterà a te e ai tuoi utenti.

Una possibile soluzione

È possibile risolvere alcuni dei problemi usando la limitazione lato server invece di fare un fattore di costo arbitrariamente grande. Immaginate se l'API chiama dove l'utente dice "datemi i dati per questa chiave" non restituisce immediatamente i risultati, ma genera una richiesta accodata che risponde solo dopo il periodo X. Ciò consentirebbe di bloccare la forzatura brute indipendentemente dal livello di hardware a cui l'utente malintenzionato ha accesso, non rallenterebbe il server con un lungo processo KDF e inoltre non penalizzerebbe gli utenti con hardware lento. Lo svantaggio ovviamente è che si tratta di un controllo lato server, quindi se il database trapelato da un hacker potrebbe andare in città in brute-forcing alla velocità del proprio hardware.

    
risposta data 18.09.2018 - 19:11
fonte

Leggi altre domande sui tag