2011-01-08 8 views
6

Alcuni anni ho chiesto qui su StackOverflow su come rendere sicuro lo storage di password PHP. Il main answer suggerisce di utilizzare il seguente algoritmo di hashing:Memorizzazione password PHP con HMAC + nonce - La casualità della nonce è importante?

function hash_password($password, $nonce) { 
    global $site_key; 
    return hash_hmac('sha512', $password . $nonce, $site_key); 
} 

La risposta suggerisce di utilizzare un casuale nonce . C'è qualche vantaggio nell'avere un nonce casuale su semplici nonce univoci?

Ad esempio, ogni utente può avere il proprio ID che non cambia. Tuttavia, supponiamo che gli ID utente siano sequenziali (creati con la funzione di incremento automatico di MySQL) e quindi non casuali. L'ID utente sarebbe un buon nonce o la casualità è importante?

Ora, ogni utente può scegliere un nome utente. Ogni utente ha il proprio nome utente che non cambia e due utenti diversi non possono avere lo stesso nome utente. I nomi utente non sono ancora casuali, ma non sono nemmeno sequenziali. I nomi utente sarebbero abbastanza buoni come nonce? Sarebbe meglio che usare l'ID utente?

+0

Il tuo nonce dovrebbe essere un sale. Un sale è casuale per definizione. Ho scritto una lunga risposta su salting qui: http://stackoverflow.com/questions/1645161/salt-generation-and-open-source-software/1645190#1645190 – Jacco

risposta

2

QUESTO E 'TUTTO SUL PRESUPPOSTO CHE un nonce è un sale ...

Se per nonce si intende un sale allora sì che richiede più tabelle arcobaleno da effettuare. Di solito una volta che il sale supera i 20 caratteri è sufficiente, ma per condizioni di sicurezza estreme si vorrebbe un nuovo salt casuale per ogni password.

Anche una buona scelta in un hash lento http://www.php.net/manual/en/function.hash.php#89574, nessun sarcasmo. Ma mi piace riparmare.

Non ho visto la metà inferiore della risposta. Elaborare: i nonces sono usati per prevenire l'uso delle tabelle arcobaleno. Se gli ID funzionerebbero dipende solo dalla lunghezza degli ID. La casualità non è tecnicamente importante, ma richiede solo più tavoli arcobaleno. Un esempio potrebbe essere, diciamo che hai usato un carattere "a" come nonce e che la password era lunga 2 caratteri, una tabella arcobaleno di a-aa, a-ab a-ac e così via avrebbe dovuto essere creata. Se ne usi una a caso ogni volta forse tutte le permutazioni di "a" dovrebbero essere fatte + tutte le permutazioni degli altri personaggi casuali.

Ma in generale le tabelle arcobaleno richiedono molto tempo. Quindi, se vieni con un sale così a lungo, è probabile che il tavolo arcobaleno per esso non esiste.

+0

Questa risposta è corretta ma non ha nulla a che fare con il domanda. HMAC non è un hash ma un algoritmo MAC. Chiamato anche hash con chiave. Quindi, il nonce è nella domanda non è il termine corretto. Dovrebbe essere la chiave (privata). E in tal caso, una chiave è sicura (a meno che non lavori per o desideri proteggere contro un'agenzia nazionale). – Henri

+0

Quindi il nome "NoviceCoding" ... Grazie mille per la spiegazione. Cerco di condividere la poca conoscenza che ho di queste cose, ma come questa volta era irrilevante. Grazie ancora. – NoviceCoding

+0

Un sale * deve essere casuale *. Un id utente non è sicuramente adatto per l'uso come sale: ci sono molti sistemi là fuori con un id utente 1. (c'è anche un'alta probabilità che l'account amministratore sia da qualche parte negli id ​​bassi) Qualunque cosa sia prevedibile indebolisce lo schema. – Jacco

0

Per la memorizzazione sufficiente per utilizzare la password:

sha512(salt + password) 

salt dovrebbe essere casuale e unica per ogni utente. Il sale casuale renderà impossibili le tabelle hash precalcolate: ogni utente richiederà le proprie tabelle hash calcolate. Se userai sale saltuale, la possibilità che la tabella precalcolata esista sarà più alta.

La posizione di sale prima della password consente di nascondere i modelli di hash nel caso in cui alcuni utenti abbiano la stessa password.

Nonce non è necessario, perché è per prevenzione un attacco di risposta. Questa protezione non è possibile nella tua architettura.

Utilizzando HMAC per evitare collisioni è inutile, perché a) che usiamo hash non per MAC, b) per rendere probabilità di collisione del 50% per SHA-512 you need to calculate circa 2^256 valori.E 2^256 è un numero veramente astronomico.

+0

Questo è un cattivo consiglio. HMAC è lo standard indiscusso per l'archiviazione delle password dal momento che è estremamente impegnativo in termini di risorse per la forza bruta. Utilizzare HMAC + SHA512 se si desidera utilizzare SHA. – mattbasta

2

Ho trovato che c'era un tutorial abbastanza bello scritto online su questo argomento. Non ricordo bene dove su google ho trovato, ma fammi vedere se riesco a rompere la funzione abbastanza bene me stesso come è proprio davanti a me ...

Prima la funzione, può creare una chiave lunghezza di qualsiasi dimensione. Mi sono permesso di commentare è abbastanza pesantemente ...

function pbkdf2($password,$salt,$iter_count = 1500,$key_length = 32,$algorithm = 'sha512') 
{ 
    /* 
     @param string password -- password to be encrypted 
     @param string salt -- salt to encrypt with 
     @param int iter_count -- number of times to iterate blocks 
     @param key_length -- length of key to return 
     @param $algorithm -- algorithm to use in hashing 

     @return string key 
    */ 

    //determine the length of the hahs 
    $hash_length = strlen(hash($algorithm,NULL,TRUE)); 
    //determine the number of key blocks to compute 
    $key_blocks = ceil($key_length/$hash_length); 
    //initialize key 
    $key = ''; 

    //create the key itself 
    //create blocks 
    for($block_count = 1;$block_count <= $key_blocks;$block_count++) 
    { 
     //initalize hash for this block 
     $iterated_block = $block = hash_hmac($algorithm,$salt.pack('N',$block_count),$password,TRUE); 
     //iterate blocks 
     for($iterate = 1;$iterate <= $iter_count;$iterate++) 
     { 
      //xor each iterate 
      $iterated_block ^= ($block = hash_hmac($algorithm,$block,$password,TRUE)); 
     } 
     //append iterated block 
     $key .= $iterated_block; 
    } 
    //return the key 
    return substr($key,0,$key_length); 
} 
  1. prima cosa che fa è capire la lunghezza del hash.
  2. Successivo determina quanti sono necessari blocchi fondamentali per la lunghezza della chiave specificata
  3. Poi inizializza l'hash (chiave) per tornare
  4. insiemi il ciclo for che creerà ogni blocco
  5. batte hash iniziale del blocco con il blocco contatore in binario allegata al sale
  6. inizia il ciclo per scorrere i tempi iter_count blocco $ (creare un hash di sé)
  7. XOR ogni iterare e lo aggiungono $ iterated_block (xor precedente hash corrente)
  8. XOR ciclo termina
  9. accodamento $ iterated_block a $ chiave per ogni blocco
  10. blocco del ciclo termina
  11. ritorno la chiave

sento che questo è probabilmente il modo migliore per farlo. Forse sono troppo paranoico?

Problemi correlati