È un buon modo per memorizzare le password in un'applicazione Web?

5

Mi è stato assegnato il compito di trovare un modo migliore per archiviare le password e ho trovato questo Algorithm. La mia comprensione di Crypto non è abbastanza strong, ma qualcuno può controllarlo per favore?

Ingressi: Nome utente Passcode

Algoritmo:

Passa Username attraverso uuid (RFC 4122) per ottenere l'hash Username (questo è principalmente per generare una stringa di lunghezza fissa in modo che il DB possa indicizzarlo in modo ordinato)

Seleziona uuid dal database per ottenere l'ID.

Salt = md5 (Hashed Username + db ID + Password)

Elimina le variabili di input.

sha512 (password, salt, rounds)

Dove round = 2 ^ ((giorni tra ora - 1 gennaio 2008)) / 365) * fattore (forse 50000).

Elimina i suggerimenti nella stringa risultante su sale e giri (possono essere rigenerati).

Archivia il payload hash.

Output:

Una stringa da testare contro la stringa memorizzata, cambia ogni accesso a causa di cicli in costante aumento.

    
posta user13037 13.09.2012 - 21:14
fonte

8 risposte

16

Non farlo. Per favore, non farlo. Farà coloro che verranno dopo di te odiarti. E può o non può essere affatto sicuro.

Basta usare una libreria esistente per le password di hashing. Preferibilmente uno che utilizza la libreria crypt(3) sotto (a seconda della lingua, ne suggerirei uno, ma non hai indicato una lingua di destinazione).

Il tuo metodo di generazione di sale non è orribile, ma non è neanche bello.

Basta attenersi agli algoritmi esistenti. Esistono e sono consigliati per una ragione ... Non cercare di inventare il tuo solo per essere intelligente. Potrebbe funzionare, ma di solito non lo farà ...

    
risposta data 13.09.2012 - 23:16
fonte
8

hashing ID utente?

Pass Username through uuid (RFC 4122) to get hashed Username (this is mostly to generate a fixed length string so that the DB can index it tidily)

Select uuid from database to get ID.

Questo è inutile: i database possono indicizzare stringhe di lunghezza variabile semplicemente. Infatti, lo faranno meglio di un UUID dato che la maggior parte dei nomi utente sono lunghi meno di 32 caratteri, quindi sei solo:

  • Rendere il tuo programma più complicato
  • Rendere gli indici più grandi

Salt

Salt = md5(Hashed Username + db ID + Password)

Perché? Il sale dovrebbe essere un valore unico, quindi questo enorme overkill e discutibile è meno utile di un sale completamente casuale. Prendi alcuni dati casuali da qualche parte ( /dev/random o qualunque sia Windows) e memorizzali nel database. Stai comunque cercando la password, quindi anche afferrare il sale non ti rallenterà affatto.

Il fatto che tu stia salendo questi valori suggerisce che non capisci veramente cosa sta succedendo.

  • Se questo valore è stato memorizzato ovunque, lo schema di hashing della password è infranto (perché md5(user+id+password) è molto più facile a bruteforce rispetto a PBKDF2-sha512(password, salt, rounds) . Probabilmente sai meglio che memorizzarlo, ma qualcun altro potrebbe venire più tardi e "ottimizzare" "è ..
  • Se non è memorizzato da nessuna parte, non ha senso chiuderlo. Usa semplicemente user+id+password come sale direttamente.

Round dinamici

Where rounds = 2 ^ ((days between now - 1st Jan 2008)) / 365) * factor (50000 perhaps).

Quindi cosa succede quando lo guardi domani? All'improvviso il numero di round è diverso e le tue password non corrispondono. Dovrai memorizzarlo da qualche parte e il database è il posto più facile. Inoltre, se il tuo hardware può supportare un numero maggiore di round, perché non iniziare solo con il numero più alto che riesci a trovare?

Se vuoi ottenere un nuovo hash ogni volta che qualcuno accede, genera sempre un nuovo salt ogni volta.

Conclusione

Puoi ottenere tutto ciò che desideri, senza le vulnerabilità della sicurezza semplicemente facendo le cose nel modo standard (bcrypt o PBKDF2, con sali casuali e rounds imposta il valore più alto che puoi gestire).

    
risposta data 14.09.2012 - 00:36
fonte
6

C'è un difetto molto significativo (supponendo che intendessi lo standard cryptogrfahic salt che è necessariamente archiviato nel database):

salt = md5(Hashed Username ++ db_ID ++ Password)

Con i sali normali sono archiviati nel database e probabilmente il nome utente è memorizzato in una colonna separata, quindi se un amministratore malintenzionato o un iniettore SQL riesce a mettere le mani sul DB, possono usare solo i sali MD5 memorizzati nella forza bruta le password. Dato che MD5 è un sale molto debole, a meno che la password non sia un'entropia molto alta, una GPU può craccarla provando diversi miliardi di password al secondo [1] .

Tuttavia, potresti aver inteso che il tuo database memorizza solo username e multi_round_hash_sha512_hash ; in particolare non memorizzando il nome utente derivato 'salt' come nell'esempio seguente (dove ++ è concatenazione):

db_id = uuid(username);
username_derived_salt = md5(username ++ db_id ++ password);
# this salt not stored in DB
multi_round_hash = password;
for(i=0; i < rounds; i++) {
    multi_round_hash = sha512(multi_round_hash ++ username_derived_salt);
}

In questo caso, questo non è un difetto, anche se è fondamentalmente equivalente all'utilizzo di un nome utente stesso come un sale con un po 'di oscurità su di esso.

Inoltre, l'utilizzo di un numero dinamico di round che aumenta nel tempo sembra inutilmente complicato e non vedo il vantaggio rispetto a un numero fisso (diciamo 100.000 round, che potresti decidere di aumentare a un certo punto). Prevedo molti problemi di implementazione (i timestamp sono disallineati tra gli utenti, quindi il numero di round è diverso, con un cron job che aggiunge un giro extra agli hash memorizzati ogni giorno - possibili problemi con gli utenti che cercano di effettuare il login intorno a mezzanotte; . Per lo meno memorizzare il numero di cicli con la password hash e test molto accuratamente.

Usare qualcosa come bcrypt / PBKDF sembra molto più semplice.

    
risposta data 13.09.2012 - 23:16
fonte
3

Oltre alle altre buone risposte qui, dato che stai usando SHAxxx potresti trovare interessante che ci sia hardware che può crea rapidamente hash SHA256 come velocità straordinarie. Anche se al momento non si tratta di una vulnerabilità di sicurezza, bcrypt è progettato per resistere agli attacchi basati su FPGA.

Anche il tuo codice sembra violare almeno una best practice di crittografia : non inventare la tua crittografia personale codice.

La soluzione preferita è utilizzare bcrypt o PBKDF2

    
risposta data 14.09.2012 - 02:36
fonte
3

Sembra buono, a parte il tuo sale non è casuale. Lo stai facendo davvero (inutilmente) complicato. Potresti semplicemente usare Bcrypt che ti semplifica molto la vita.

    
risposta data 13.09.2012 - 21:50
fonte
1

Si consiglia sempre di utilizzare un meccanismo standard e comprovato per la memorizzazione delle password. Sebbene il tuo algoritmo possa essere abbastanza sicuro, come suggerito dalle altre risposte, potrebbe essere difficile per gli altri in futuro. Quindi, sono stati usati metodi comuni come l'utilizzo di PBKDF2 per creare hash di password. link questo link è un'ottima risorsa che fornisce il codice / la tecnica per memorizzare gli hash delle password ed è disponibile per le lingue più comuni .

    
risposta data 13.09.2012 - 23:58
fonte
0

MD5 è un algoritmo di hashing crittografico progettato per la velocità, e quindi è un problema per la memorizzazione delle password, anche con un salt. Usa qualcosa di lento come HMAC con un sale complesso che è accettabilmente più lento - sì significa che le operazioni di accesso saranno impercettibilmente più lente ma significa anche che chiunque si impadronisca del tuo database con password hash deve spendere 10 volte più password cracciando così 10 volte meno le password verranno esposte in caso di un attacco catastrofico.

    
risposta data 22.09.2012 - 00:01
fonte
-1

anche se stai salendo i tuoi hash penso che dovresti usare sha1 invece di hashing md5 perché è stato trovato che md5 è insicuro

    
risposta data 13.09.2012 - 23:18
fonte

Leggi altre domande sui tag