E 'possibile aumentare il costo di BCrypt o PBKDF2 quando è già calcolato e senza la password originale?

31

Volevo solo sapere se è possibile aumentare i costi (iterazioni) di questi due algoritmi off-line. Voglio aumentare il costo di ogni anno delle password dei miei utenti.

Una soluzione è ricalcolarle quando l'utente effettua l'accesso, ma un utente potrebbe non aver effettuato l'accesso in quel periodo e non voglio aspettare fino a quando non effettua l'accesso.

Questo potrebbe essere fatto con lo stretching delle password (ad esempio iterando su un hash sha-256), ma non sono a conoscenza se ciò è possibile con BCrypt e / o PBKDF2. Grazie.

    
posta skantos 08.06.2012 - 22:48
fonte

5 risposte

14

PBKDF2 e Bcrypt non supportano l'aumento del costo, a partire dall'output con un dato numero di iterazioni, senza conoscenza della password. Non c'è una ragione intrinseca per quello; un processo di hashing della password potrebbe consentire tale allungamento offline pur rimanendo "buono". Ma questi algoritmi capita di non permetterlo.

Ciò che può essere fatto è il seguente: un normale output bcrypt o PBKDF2 include il s salt, il conteggio iterativo i e l'output hash v . Nelle implementazioni di bcrypt, i tre valori sono spesso codificati in caratteri stampabili (con una codifica tipo Base64); vedi ad esempio questa risposta . Supponendo che tu abbia s e v , puoi memorizzare quanto segue:

  • the salt s ;
  • un conteggio iterativo i ;
  • un conteggio iterativo aggiuntivo j ;
  • il valore h (h (h (... h (h (v)) ...))) che è il risultato di hashing v ripetutamente, con una funzione di hash sicura h , fatta j volte.

Per la verifica della password, devi ricalcolare bcrypt / PBKDF2 dalla password specificata (usando s e i ), e poi eseguire l'hash del valore risultante j volte, per vedere se corrisponde al valore memorizzato.

Questo è per lo più sicuro, se usi una strong funzione di hash per h , come SHA-256. Si può dimostrare che l'hashing ripetuto riduce lo spazio dei valori possibili, ma dovrebbe raggiungere un "ciclo" interno di dimensione all'incirca sqrt (N) se i valori di output dell'hash sono in uno spazio di dimensioni N ; inoltre, se quel ciclo è abbastanza piccolo da essere esplorato esaurientemente, può essere calcolata una collisione sulla funzione hash h (vedi questa pagina per un bel diagramma). Quindi, se h è resistente alle collisioni (come SHA-256), lo schema sopra è sicuro.

Il punto importante è che puoi aumentare j in seguito, in modo offline. Tuttavia , nota che questo tipo di stretching si basa sul costo di elaborazione coinvolto nel fare molti calcoli di funzioni hash extra. Sfortunatamente, le solite funzioni di hash come SHA-256 si adattano molto bene a ciò che la GPU può fare; quindi, il vantaggio ottenuto in quel modo sull'attaccante potrebbe non essere così grande come inizialmente desiderato. In altre parole, l'uso dello stretching descritto sopra annulla qualsiasi vantaggio di bcrypt su PBKDF2 (vedi questa risposta per una discussione su questo argomento). Potresti applicarlo come misura temporanea, fino a quando il suddetto utente non ritorna, in modo che il passaggio bcrypt possa essere eseguito di nuovo con un conteggio di iterazioni più elevato ( i ).

Inoltre , lo schema che descrivo sopra è crypto fatto in casa, e questo è male. Posso farla franca perché sono assolutamente fantastico, ma questo non può essere promosso su base generale.

    
risposta data 28.10.2012 - 17:33
fonte
8

bcrypt dipende da alghoritm di Eksblowfish che è definito come:

Eksblowfish(cost, salt, key)
  state = InitState()
  state = ExpandKey(state, salt, key)
  repeat (2^cost)
    state = ExpandKey(state, 0, key)
    state = ExpandKey(state, 0, salt)
  return state

Questo codice mostra il numero di iterazioni. Poiché l'utilizzo di bcrypt è: bcrypt(cost, salt, key) , la variabile cost è log2 di iterazioni. Quindi aggiungere uno a cost raddoppia il tempo.

Ogni round utilizza la password iniziale (chiave), non è possibile aggiungere giri aggiuntivi senza di essa. Quindi, per Bcrypt, la risposta è no.

    
risposta data 10.06.2012 - 00:14
fonte
7

Come menzionato p

risposta data 12.06.2012 - 17:58
fonte
4

Ho avuto lo stesso requisito e l'ho risolto in questo modo:

  • Hash il sale e la password nel solito modo con PBKDF2 e un fattore di lavoro che è attualmente 16 (cioè 2 ^ 16 iterazioni). Memorizza il sale, l'hash, il fattore di lavoro, ecc. Come una riga in una tabella di database.
  • In modo asincrono (ovvero non influisce sull'utente finale) fallo altre 3 volte, aumentando il fattore di lavoro di 1 ogni volta. Così ora ho 4 file di database per quell'utente, con fattori di lavoro rispettivamente di 16, 17, 18 e 19
  • Uso sempre la riga con il fattore di lavoro più basso per verificare la password, ma ogni 2 anni elimino la riga con il fattore di lavoro più basso.
risposta data 08.04.2013 - 03:14
fonte
0

Immagina che fosse possibile allungare il numero di cicli di una chiave senza la password originale. Se così fosse, sarebbe possibile costruire una tabella arcobaleno che mappa dall'output dopo 1 iterazione all'output dopo 1000 iterazioni. La tabella renderebbe rapido l'annullamento di 1000 iterazioni.

Dato quel tavolo, un cracker potrebbe invertire 1000 iterazioni fino a 1 e poi provare a crackare il PBKDF con solo 1 iterazioni. Ciò indebolirebbe l'algoritmo.

    
risposta data 31.08.2012 - 16:22
fonte

Leggi altre domande sui tag