2013-01-18 17 views
12

Sto passando un sito a un binario. È un sito abbastanza grande con 50k + utenti. Il problema è che il metodo di hashing della password esistente è estremamente debole. Ho due opzioni:Spostare le vecchie password in un nuovo algoritmo di hashing?

1) Passare un nuovo algoritmo, generare password casuali per tutti e poi e-mail li le password e richiedono il cambiamento subito dopo

2) Implementare nuovo algoritmo ma utilizzare il vecchio prima di e poi ha cancellato il risultato. Per esempio:

Password: ABCDEF = Algoritmo 1 => xj31ndn = Algoritmo 2 => $ 21aafadsada214

Eventuali nuove password avrebbe bisogno di passare attraverso l'algoritmo originale (MD5) e poi avere il risultato di tale hash, se ha senso? C'è qualche svantaggio in questo?

risposta

2

È possibile creare un nuovo campo password con tutti gli utenti che ha aggiornato la propria password con il nuovo metodo password e solo aggiornare tutti con l'opzione 2.

In combinazione con questa forzatura aggiornamento password su di accesso per tutti gli utenti con il vecchio metodo di password sposta automaticamente tutti gli utenti attivi sul nuovo metodo di password.

1

Un'alternativa potrebbe essere quella di mantenere entrambe le hash a disposizione per la fase di migrazione in colonne separate del database:

  • Se il nuovo hash non esiste durante il login, verificare con il vecchio hash e salvare il nuovo hash ed elimina il vecchio hash.
  • Se il nuovo hash esiste, utilizzare solo questo per verificare.

Quindi, dopo un po 'di tempo, verranno lasciati solo i nuovi hash, almeno per gli utenti che hanno effettuato l'accesso almeno una volta.

20

Normalmente non è necessario reimpostare le password, si può solo aspettare che l'utente effettui il login la volta successiva.

  1. Prima prova per verificare la password inserita con il nuovo algoritmo. Le nuove password e le password già convertite non impiegheranno più tempo per la verifica.
  2. Se non corrisponde, confrontarlo con il vecchio algoritmo di hash.
  3. Se il valore hash precedente corrisponde, è possibile calcolare e memorizzare il nuovo hash, poiché si conosce la password.

Ogni sistema di memorizzazione password deve avere la possibilità di passare a un algoritmo di hash migliore, il problema non è un problema di migrazione una tantum. Gli algoritmi di hash della buona password come BCrypt hanno un fattore di costo, di volta in volta è necessario aumentare questo fattore di costo (a causa dell'hardware più veloce), quindi è necessario la stessa procedura necessaria per la migrazione.

L'opzione 2 con hashing del vecchio hash è una buona cosa, se il tuo primo algoritmo è veramente debole e vuoi dare più protezione immediatamente. In questo caso è possibile calcolare un doppio hash e sostituire il vecchio hash nel database con il nuovo doppio hash.

$newHashToStoreInTheDb = new_hash($oldHashFromDb) 

Si dovrebbe anche segnare questa password-hash (see why), in modo da poter riconoscere come doppio hash. Questo può essere fatto in un campo di database separato, oppure puoi includere la tua firma. Le moderne funzioni di hash delle password includono anche una firma dell'algoritmo, in modo che possano eseguire l'aggiornamento a nuovi algoritmi e possono ancora verificare gli hash meno recenti. L'esempio mostra la firma di un hash bcrypt:

$2y$10$nOUIs5kJ7naTuTFkBy1veuK0kSxUFXfuaOKdOKf9xYT0KKIGSJwFa 
___ 
| 
signature of hash-algorithm = 2y = BCrypt 

La verifica dovrebbe funzionare in questo modo:

  1. decidere se è un doppio hash.
  2. Se si tratta di un nuovo hash, chiamare la nuova funzione hash per verificare la password immessa e il gioco è fatto.
  3. Se si tratta di un doppio hash, confrontarlo con l'algoritmo double-hash new_hash(old_hash($password)).
  4. Se il valore di hash doppio corrisponde, è possibile calcolare e memorizzare il nuovo hash.
+0

A mio parere, il doppio hashing è un'idea orribile. Uno dei motivi per cui hai cancellato una password, è che se il tuo hash è trapelato, non possono ancora autenticarsi come utente. Se si esegue new_hash ($ raw_password) per primo, un utente può accedere inserendo il vecchio hash trapelato nel campo della password. Sconfiggere lo scopo di passare a un algoritmo di hash sicuro. – Lemon

+0

@Lemon - Ovviamente il vecchio hash della password nel database verrà sostituito con il doppio hash, ma hai ragione, questa non è la soluzione ottimale. Ho modificato la risposta per mostrare le migliori pratiche, utilizza ancora l'hashing doppio, ma segna il vecchio hash. – martinstoeckli

8

La soluzione più semplice è probabilmente aggiungere una colonna "tipo hash password" al database. Impostalo inizialmente su "vecchio"; quando un utente effettua il login, re-hash la password usando il nuovo algoritmo e imposta il tipo di database su "nuovo".

Una variante di questo metodo è per memorizzare il tipo di hash come parte della stringa di hash. Funziona altrettanto bene, purché sia ​​possibile distinguere in modo univoco i diversi formati hash e ha il vantaggio che è possibile includere anche altri parametri necessari (come lo salt e il fattore di lavoro per key stretching) nella stessa stringa senza avere aggiungere campi aggiuntivi per ciascuno al tuo database.

Per esempio, questo è l'approccio utilizzato dalla modern Unix crypt(3) implementations (e le corrispondenti funzioni in vari linguaggi di alto livello come PHP): un classico DES-based (e orribilmente debole) hash della password sarebbe simile abJnggxhB/yWI, mentre un (leggermente) più moderno hash potrebbe apparire come $1$z75qouSC$nNVPAk1FTd0yVd62S3sjR1, dove 1 ha specificato il metodo di hashing, z75qouSC è il sale e nNVPAk1FTd0yVd62S3sjR1 l'hash effettivo e il delimitatore $ viene scelto perché non può apparire in un hash DES vecchio stile.


Il metodo si suggeriscono, dove i nuovi hash sono calcolate come:

hash = new_hash(old_hash(password)) 

può essere utile in alcuni casi, in quanto consente a tutti i record esistenti da aggiornare, senza dover attendere gli utenti di accedere. Tuttavia, è sicuro solo se la vecchia funzione di hash conserva una quantità sufficiente di entropia nelle password. Ad esempio, anche una funzione di hash crittografica abbastanza vecchia e debole, come unsalted MD5, ad esempio, sarebbe abbastanza buona, poiché il suo output dipende dall'intero input e ha fino a 128 bit di entropia, che è più di quasi qualsiasi password avrà (e più che abbastanza per resistere ad un attacco di forza bruta, comunque). D'altra parte, provare ad applicare questa costruzione usando la vecchia funzione crypt basata su DES (3) come il vecchio hash sarebbe disastroso, poiché la vecchia crypt (3) ignorerebbe tutti tranne i primi 8 caratteri di ciascuna password (come bene come i pezzi più significativi anche di quei personaggi).

+0

Basta aggiungere che memorizzare "vecchio" o "nuovo" come valori di dati è una pessima idea. Cosa viene dopo la nuova? Una volta ho lavorato con un modello di dati chiamato "NewModel", che era tutto tranne. Era una fonte di costante confusione. – marcp

Problemi correlati