2013-02-21 2 views
31

Dire che volevo memorizzare una password per un utente, sarebbe il modo giusto per farlo con la funzione password_hash() di PHP 5.5 (o questa versione per PHP 5.3.7+: https://github.com/ircmaxell/password_compat)?Utilizzo della funzione password_hash di PHP 5.5 e password_verify

$options = array("cost" => 10, "salt" => uniqid()); 
$hash = password_hash($password, PASSWORD_BCRYPT, $options); 

Poi vorrei fare:

mysql_query("INSERT INTO users(username,password, salt) VALUES($username, $hash, " . $options['salt']); 

Per inserire nel database.

Poi, per verificare:

$row = mysql_fetch_assoc(mysql_query("SELECT salt FROM users WHERE id=$userid")); 
$salt = $row["salt"]; 
$hash = password_hash($password, PASSWORD_BCRYPT, array("cost" => 10, "salt" => $salt)); 

if (password_verify($password, $hash) { 
    // Verified 
} 
+1

Hmm, c'è qualcosa di strano qui, avete array ("costo" => 10, e nulla dopo? –

+0

fisso, dispiace. –

+0

Sei ancora manca a) –

risposta

57

Ignorando i problemi con le sue dichiarazioni di database per il momento, risponderò alla domanda per quanto riguarda password_hash.

In breve, no, non è così che si fa. Non si desidera memorizzare solo il sale, è necessario memorizzare sia l'hash che il sale, quindi utilizzare entrambi per verificare la password. password_hash restituisce una stringa contenente entrambi.

La funzione password_hash restituisce una stringa che contiene sia l'hash che il sale. Quindi:

$hashAndSalt = password_hash($password, PASSWORD_BCRYPT); 
// Insert $hashAndSalt into database against user 

Poi, per verificare:

// Fetch hash+salt from database, place in $hashAndSalt variable 
// and then to verify $password: 
if (password_verify($password, $hashAndSalt)) { 
    // Verified 
} 

Inoltre, come suggeriscono i commenti, se siete interessati nella sicurezza si consiglia di guardare mysqli (ext/mysql is deprecated in PHP5.5) e anche questo articolo su SQL injection: http://php.net/manual/en/security.database.sql-injection.php

+0

Stai suggerendo che usi un meccanismo di sale, ma non immagazzini il sale? In tal caso, come recupererai il sale originale utilizzato per creare l'hash originale, sul quale controllare quando l'utente tenta di accedere? –

+1

Salt e hash vengono restituiti in una stringa singola insieme da password_hash. – Pete

+0

Quando dici che ignorerai i problemi con le dichiarazioni del database per ora, sono stati i problemi menzionati in fondo al post? –

4

Non si deve immettere il proprio sale, lasciare il sale vuoto, la funzione genererà un buon sale casuale.

Inserire nel database (o file o qualsiasi altra cosa si usi) tutta la stringa restituita dalla funzione. contiene: id di algoritmo, costo, sale (22 caratteri) e password hash.

L'intera stringa è necessaria per utilizzare password_verify(). Il sale è casuale e non fa male a cadere nelle mani sbagliate (con password hash). Questo impedisce (o molto difficile) di usare set pronti generati liste di password e hash - tabelle arcobaleno.

È necessario considerare il parametro costo aggiuntivo. Predefinito (se omesso) è 10 - se superiore, funzione hash di calcolo più lungo. L'aumento del costo di 1, doppio tempo necessario per generare un hash (e quindi allungare il tempo che serve per rompere la password)

$hash = password_hash($password, PASSWORD_BCRYPT, array("cost" => 10)); 

si dovrebbe impostare questo parametro in base a controllo della velocità sul vostro server. Si consiglia di eseguire la funzione 100 ms + (alcuni preferiscono renderlo 250 ms). Di solito il costo = 10 o 11 è una buona scelta (nel 2015).

Per aumentare la sicurezza, è possibile aggiungere alle password una stringa segreta lunga (50-60 caratteri è una buona scelta). prima di utilizzare password_hash() o password_verify().

$secret_string = '[email protected]#[email protected]#$234'; 
$password = trim($_POST['user_password']) . $secret_string; 
// here use password_* function 

Attenzione Utilizzo del PASSWORD_BCRYPT per il parametro algo, porteranno al parametro della password troncati ad una lunghezza massima di 72 caratteri.

Se $ password sarà più lunga di 72 caratteri e si modificherà o aggiungerà l'hash di 73 o 90 caratteri non cambierà. Facoltativo, il blocco $ secret_string dovrebbe essere alla fine (dopo la password dell'utente e non prima).

6

Nota questo da php.net

Attenzione

L'opzione del sale è stato deprecato in PHP 7.0.0. Ora è preferito usare semplicemente il sale che viene generato di default.

Conclusione? Dimentica l'opzione di sale.

Questo sarebbe abbastanza password_hash('password', PASSWORD_DEFAULT) * (o _BCRYPT)

9

utilizzando il proprio sale non è raccomandato e, a partire dal PHP 7, its use is deprecated. Per capire perché, read the author's thoughts

Una cosa è diventata evidente a me: l'opzione sale è pericoloso. Devo ancora vedere un singolo utilizzo dell'opzione di sale che ha stato anche decente. Ogni utilizzo varia da cattiva (passando mt_rand() uscita) a pericolose (stringhe statiche) a folle (passando la password come proprio il sale).

sono giunto alla conclusione che non credo che dovremmo consentire agli utenti di specificare il sale.