Il limite di 72 caratteri di BCrypt e il suo utilizzo come algoritmo di digest generale

13

Obiettivo: disporre dell'autenticazione basata su token / cookie che non richiede il mantenimento delle sessioni sul server

TL; DR: qual è il meccanismo accettato per aggirare la limitazione di 72 caratteri di BCrypt?

Versione lunga:

Dopo aver letto questa risposta ho tentato di implementare l'autenticazione su un server basato su REST usando BCrypt come algoritmo di hashing e un Rotante segreto lato server. L'idea di base era che, una volta completata l'autenticazione con un nome utente e una password, il server avrebbe impostato un cookie contenente un hash basato sulla concatenazione di quanto segue:

  • Il segreto lato server
  • L'ID utente e i gruppi a cui appartiene l'utente
  • L'ora in cui il token è stato distribuito

Questo verrà quindi sottoposto a hash con un salt, e il risultato andrebbe nel cookie, per essere letto e verificato dal server (possibile perché l'ID utente, i gruppi e la data vengono trasmessi in chiaro dal client, e il segreto lato server è in memoria, con il segreto che serve come garanzia che il client non ha fatto tutti gli altri valori su se stessi).

Tutto questo ha funzionato bene fino a quando ho realizzato che BCrypt ha un limite di 72 caratteri sul testo in chiaro hash (qualsiasi cosa dopo che questi 72 caratteri non influenzano l'hash dell'output).

Questo è un problema perché i dati di cui sopra ammontavano a più di 72 caratteri e consentendo a tempo, ID utente, gruppi o chiave segreta di essere "ultimi" nell'input e non influenzare l'output, aprono buchi nella sicurezza del sistema (I vecchi token sono infinitamente validi, oppure le persone possono modificare arbitrariamente il loro ID utente / ruolo).

Ironia della sorte, quando finalmente ho capito perché il mio sistema produceva identici hash basati su input diversi e cercati su google, sembra questo tipo di situazione era previsto da alcuni .

In ogni caso, la domanda: Qual è il meccanismo accettato per aggirare la limitazione di 72 caratteri di BCrypt?

Alcuni pensieri preventivi: la creazione delle tue variazioni sugli algoritmi crittografici standard è qualcosa di cui sono stato avvisato per tutto il tempo che posso ricordare, quindi non sono sicuro al 100% quale sarebbe la migliore linea d'azione.

Le opzioni ovvi includono:

  • suddivisione in blocchi dell'ingresso e applicazione di BCrypt a turno a turno e / o in cascata;
  • utilizzando un altro hash (non crittografico?) sull'input per ridurne le dimensioni
  • usando la compressione semplice (ma potrebbe essere inefficace con un pezzetto di testo in chiaro)
  • passaggio a un altro algoritmo (SHA-3 è stato recentemente finalizzato, per esempio).

(potrebbero esserci altre cose sbagliate con l'idea di cui sopra, nel qual caso sarei naturalmente felice di essere corretto!)

    
posta Gijs 12.10.2012 - 18:30
fonte

3 risposte

16

Il meccanismo accettato è "non farlo".

A cosa serve bcrypt? È buono a essere lento . Perché vuoi che una funzione crittografica, o semplicemente una funzione, sia lenta? Questo ha senso solo quando l'input della funzione è un segreto di bassa entropia , che significa "un valore che l'avversario potrebbe concepire, e realisticamente, esplorare esaustivamente". Le password sono segreti a bassa entropia: è noto che quando gli esseri umani sono autorizzati a scegliere stringhe segrete nella privacy del loro cervello, la maggior parte selezionerà le password "spiritose" che sono completamente deboli contro attacchi dizionario . L'unica difesa rimanente consiste nell'impiegare l'uso di un processo di hashing intrinsecamente lento, che equivale all'invio di tutti i computer coinvolti (e, in particolare, i computer degli aggressori) ai primi anni '80, quando 1 MHz era una frequenza CPU molto elevata.

Nel tuo caso, il "valore segreto" è il segreto del server ; non dovrebbe essere di bassa entropia (il server è una macchina, non un essere umano, può ricordare lunghe chiavi). Se il segreto del server è un valore di bassa entropia, allora lo stai facendo male.

Pertanto, non c'è bisogno di bcrypt o di qualsiasi altra funzione deliberatamente rallentata qui. Quello che in realtà desideri è un Codice di autenticazione dei messaggi : desideri memorizzare alcuni valori sul lato client (come cookie), ma vuoi anche controllare che non ti vengano restituiti valori falsi; questa è una questione di integrità e un MAC è lo strumento giusto per questo. Usa HMAC / SHA-256, con il "segreto del server" come chiave MAC (il tuo hashing fatto in casa di diversi valori, incluso il server segreto, è solo un MAC fatto in casa sotto mentite spoglie, quindi puoi semplicemente farlo riutilizzando lo standard, soluzione robusta, con controllo esperto, e questo è HMAC).

Ovviamente, una volta che iniziamo ad usare lo storage lato client, diventa allettante memorizzare valori che il cliente stesso non dovrebbe imparare. Al requisito integrità , aggiungiamo riservatezza . Per questo, abbiamo bisogno di crittografia. Fare correttamente la crittografia è difficile e combinare ancora più crittografia e MAC. In tal caso, fai un favore a te stesso: utilizza una modalità di crittografia autenticata , che eseguirà correttamente con il minimo sforzo (ti consiglio EAX ).

Suggerendo Keccak (SHA-3), dimostri di essere affetto da una malattia molto comune, che può essere chiamata la "sindrome di iPhone": desideri ardentemente il nuovo gadget. Smettila. In particolare, quando si tratta della sicurezza in generale e della crittografia, ciò porterà solo a una sofferenza enorme. Nella crittografia, "nuovo" è un altro nome per "cattivo".

Il miglior tipo di algoritmo crittografico è vecchi algoritmi che sono ancora vivi . Non esiste un criterio migliore per la sicurezza. In questo senso, SHA-2 è migliore di SHA-3, e lo rimarrà in futuro, fino a quando non si troverà un problema con queste funzioni. Le stesse persone del NIST raccomandano esplicitamente SHA-2 e negano qualsiasi suggerimento che SHA-3 sarebbe meglio di SHA-2.

    
risposta data 12.10.2012 - 19:51
fonte
2

Potresti usare un'altra funzione di derivazione della chiave come scrypt o pbkdf2 + sha2 (o sha3).

Anche se penso che questo approccio all'autenticazione sia molto dispendioso di larghezza di banda, memoria e CPU e per finire è meno sicuro. Affinché lo stiramento dei tasti sia efficace, deve essere pesante e dovrai effettuare questo calcolo per ogni richiesta. Penso che sia meglio rilasciare un nonce crittografico e ripristinare lo stato del server con un database veloce non relazionale come memcachd. Sicuramente non è "RESTful", ma è un design più efficace e più sicuro.

I migliori crittografi usano la crittografia quando non c'è altra scelta. Pianifica in caso di fallimento.

    
risposta data 12.10.2012 - 18:41
fonte
0

Sembra che tu stia cercando di mantenere lo stato della sessione senza il solito approccio di memorizzazione dei dati della sessione sul server.

Ecco un libro di cucina migliore:

  1. Autentica il nome utente e la password (qui puoi utilizzare bcrypt per la convalida della password)
  2. Inserisci tutte le informazioni sulla sessione che desideri archiviare in un blob serializzato
  3. Crittografa il blob con una potente e segreta chiave del server, usando crittografia autenticata
  4. Invia il blob in un campo cookie / modulo nascosto / ... (codificato in base64)

Alla prossima chiamata:

  1. Decifra / verifica il blob
  2. Annulla la serializzazione dei dati di sessione
  3. profitto!

Tutti questi passaggi sono stati testati in battaglia.

    
risposta data 21.09.2015 - 01:13
fonte

Leggi altre domande sui tag