it-swarm.it

Una password HMAC ed è più sicura di una password criptata o criptata?

Data un'opzione, quale dovrei scegliere, un HMAC per archiviare una password in modo sicuro o una libreria bcrypt o scrypt?

25
user917279

Per darvi un'idea corretta dei problemi e delle sottigliezze degli hash delle password di calcolo, nonché del perché HMAC non è adatto a questo problema, fornirò una risposta molto più ampia di quanto sia realmente necessario per rispondere direttamente alla domanda.

Un algoritmo hash HMAC è, essenzialmente, solo una versione con chiave di un normale algoritmo hash. Di solito viene utilizzato per verificare l'integrità e l'autenticità. La solita notazione di questo è H(m,k) = h, dove H è l'algoritmo hash HMAC, m è il messaggio, k è la chiave e h è l'hash risultante. L'idea è che due parti che condividono un k segreto possano verificare che l'altra persona sia l'autore di m. Inoltre, un utente malintenzionato non può creare un hash di messaggio senza conoscere k.

Questo viene fatto come segue:

  1. Sia Alice che Bob conoscono una chiave segreta condivisa k.
  2. Alice scrive un messaggio m e calcola l'hash HMAC usando k, ovvero H(m,k) = h.
  3. Alice invia il messaggio m e l'hash h a Bob.
  4. Bob calcola H(m,k) e lo confronta con l'hash h che Alice ha inviato. Se gli hash corrispondono, sa che Alice ha inviato il messaggio e che non è stato modificato dopo averlo hash.

Ora che hai capito cos'è HMAC, passiamo a ciò che vuoi davvero - archiviare le password in un database.

Molti anni fa, era prassi normale archiviare le password in chiaro nei database. Questa è stata una cattiva idea perché, quando il database è stato compromesso, l'attaccante ha ottenuto tutte le password. Per contrastare questo, abbiamo iniziato a eseguire l'hashing delle password nel database utilizzando algoritmi di hash crittografici unidirezionali. L'MD5 è diventato popolare, ma i punti di debolezza (collisioni, preimmagini parziali, ecc.) Hanno scoperto che non è più raccomandato. Molte persone si sono trasferite su SHA1, che è più sicuro.

Il problema con questo approccio è che è possibile costruire un'enorme tabella di hash e i corrispondenti corrispondenti. Questi sono chiamati tabelle Rainbow . Lavorano sul concetto che è più efficiente calcolare un enorme elenco di hash per tutte le possibili password (all'interno di un determinato set) e quindi memorizzarlo, in modo che possa essere rapidamente interrogato in seguito. Quindi, invece di forzare gli hash individuali, è diventato possibile semplicemente interrogare il database per un hash e ottenere immediatamente il suo testo in chiaro.

Per risolvere questo problema, i secchioni della sicurezza hanno inventato i sali. I sali sono grandi valori casuali univoci aggiunti alle password prima che vengano sottoposti a hash. Questo sale viene memorizzato con l'hash, in modo che possa essere nuovamente calcolato in seguito. Quindi, calcoliamo H(m+s) = h, quindi memorizziamo h e s nel database. Ciò fornisce un significativo protezione contro le tabelle Rainbow perché richiede essenzialmente una tabella Rainbow separata da generare per ogni sale.

Quindi, i cattivi sono tornati agli attacchi del dizionario e al cracking della forza bruta. Con l'avvento del GPU computing, è diventato possibile calcolare miliardi di hash al secondo su una scheda grafica moderatamente potente. In effetti, le persone hanno costruito computer in grado di calcolare quasi 50 miliardi di hash MD5 al secondo - piuttosto impressionante/spaventoso. La ragione per cui le GPU sono in grado di farlo è che sono progettate per eseguire un numero enorme di operazioni scalari parallele. Le operazioni scalari sono operazioni matematiche e logiche che non coinvolgono rami - cioè non hanno bisogno di fare molto/qualsiasi "se x allora do y". Gli algoritmi di hash crittografici tendono ad adattarsi a questo modello.

Per renderlo difficile, dobbiamo rendere l'operazione di hash abbastanza lenta da rendere impossibile la forzatura bruta. Gli algoritmi di hash normali (ad esempio SHA1) sono progettati per essere veloci, il che li rende inadatti a questo scopo. HMAC aggiunge pochissime spese generali e nessun margine di sicurezza aggiuntivo, quindi anche qui non è molto utile.

Creare un algoritmo di hash crittografico lento è più facile a dirsi che a farsi: è molto difficile trovarne uno che sia lento, irriducibile (cioè non può essere ottimizzato oltre il suo stato attuale) e sicuro. Esistono tre funzioni hash popolari che possono eseguire questa operazione: PBKDF2 , bcrypt e scrypt . Queste sono conosciute come funzioni di derivazione chiave adattativa, perché accettano un valore del fattore di lavoro insieme al testo in chiaro e al sale. Il fattore di lavoro modifica la quantità di tempo necessaria per calcolare l'hash ed è progettato per proteggere da futuri miglioramenti hardware.

Quindi, per un algoritmo di derivazione della chiave adattiva H, calcoliamo H(m,s,w) = h, dove m è il messaggio (password), s è il sale e w è il fattore di lavoro. Il risultante h solitamente contiene s e w, in modo che una funzione di verifica possa successivamente calcolare lo stesso hash utilizzando gli stessi parametri. Il fattore di lavoro generalmente controlla il numero di iterazioni eseguite di una primitiva crittografica interna. L'obiettivo è fare in modo che il calcolo richieda abbastanza tempo da rendere impossibile il cracking, ma non superare le risorse che abbiamo.

Al fine di fornire maggiore sicurezza contro il cracking basato su hardware dedicato, scrypt garantisce che il calcolo dell'hash sia sia difficile da CPU che da memoria, ovvero richiede risorse significative di CPU e memoria per produrre il valore hash. Questo è importante perché FPGA di solito hanno accesso a pochissima memoria immediata.

Ora sorge la domanda ovvia: se imposto il mio sito per utilizzare bcrypt, ciò non significa che il mio server debba calcolare gli hash ad alta intensità di CPU in ogni momento? Bene, se li esegui sul tuo server, allora sì, è qualcosa da prendere in considerazione. Una soluzione migliore è che il client calcoli l'hash, quindi lo invii al server su SSL. Il server può quindi confrontarlo con il valore nel database. Ciò garantisce che l'hash della password non possa essere facilmente decifrato in caso di furto (ad es. Tramite un compromesso del database) e che il server non sia sopraffatto dall'overhead del calcolo dell'hash della password. Per i siti Web, è possibile utilizzare jsBcrypt .  Aggiornamento: Questo metodo è stato segnalato come imperfetto da un commentatore di seguito. Non usarlo.

Spero che questo ti dia una buona visione d'insieme della situazione e del perché HMAC non sia adatto a questo tipo di utilizzo.

37
Polynomial

HMAC è un codice di autenticazione del messaggio ; usa una chiave. Bcrypt no. Pertanto, la scelta non è neutrale; non puoi pensare che tutte le cose siano uguali, perché non lo sono.

Sebbene nominalmente per i controlli di integrità, accade che l'HMAC (se utilizzato con una funzione hash ragionevolmente sicura, ad esempio SHA-256 o persino SHA-1) si comporti in qualche modo come "una funzione hash con una chiave". Questa non è una proprietà generica degli algoritmi MAC, ma funziona con HMAC (ecco perché può essere usata come base per un generatore casuale chiamato Hmac_DRBG ). Questo rende HMAC una potenziale scelta per l'hash della password.

Se "hash" la tua password con HMAC e l'utente malintenzionato potrebbe acquisire il tuo file/database di password con hash ma non la chiave HMAC , l'attaccante non essere in grado di decifrare le password. In quello scenario, HMAC è "migliore" di bcrypt/scrypt. Tuttavia, questo è un caso Edge. Abbiamo le password di hash perché ci preoccupiamo di scenari marginali in cui l'attaccante potrebbe violi la sicurezza abbastanza da ottenere un accesso sola lettura a parte dei file del server, ma non a lettura-scrittura accesso. Il metodo hash-with-HMAC è per uno scenario marginale in cui l'attaccante di sola lettura potrebbe ottenere la password con hash ma non la chiave, che è comunque memorizzata sullo stesso server.

Se l'attaccante è in grado di ottenere la chiave, HMAC diventa solo una semplice funzione hash per lui, e in quel caso HMAC è molto peggio di bcrypt, perché è non salato e troppo dannato veloce. È come se le password fossero associate a hash con un paio di invocazioni SHA-1. Questo scenario non è meno probabile del precedente e quindi dobbiamo considerare l'uso dell'HMAC da solo come troppo rischioso .


Per il meglio dei due mondi , applica HMAC sulla password dell'utente, e quindi elabora l'output HMAC attraverso - bcrypt ; salverai l'output di bcrypt. Poiché le implementazioni di bcrypt prevedono la password come stringa di caratteri, dovresti codificare l'output HMAC (esadecimale, Base64 ...).

Questo è più complesso di bcrypt da solo, a causa dell'utilizzo di due funzioni anziché di una, e della chiave (che porta l'intera questione spinosa della gestione delle chiavi: generazione, archiviazione, backup ...). Dato che la complessità è cattiva, raccomanderei contro di essa; usa semplicemente bcrypt da solo e non aggiungere un HMAC. Tuttavia, questa è la tua chiamata; se davvero vuoi l'HMAC, usalo oltre a bcrypt, non anziché bcrypt.

(Nota: questo è bcrypt sull'output HMAC, non viceversa, che non funzionerebbe a causa del salt che è incluso nell'output di bcrypt.)

9
Thomas Pornin

HMAC è progettato per essere molto veloce ed è in questo contesto un buon modo per aggiungere salt alla password invece di aggiungerla semplicemente. Bcrypt è molto più lento a causa della lenta inizializzazione, mentre scrypt è ancora più lento di Bcrypt perché è stato intenzionalmente progettato in questo modo. Scrypt è progettato per rendere il bruto costringendolo molto costoso dal punto di vista computazionale. Consuma molta CPU, memoria ed è anche lento da usare su GPU.

Maggiori informazioni su scrypt

2
Matrix