È mt_rand () adatto per generare un sale?

3

Supponiamo di dover seguire il codice per generare un sale blowfish casuale per il salvataggio di una nuova password:

$blowfishCharacters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./';
$salt = '';
$type = '2a';
$cost = '08';

$maxIndex = strlen($blowfishCharacters) - 1;

for ($i = 0; $i < 22; $i++) {
        $salt .= $blowfishCharacters[mt_rand(0, $maxIndex)];
}

$salt = '$' . $type . '$' . $cost . '$' . $salt;
$pass = crypt($password, $salt);

Ho letto diverse discussioni su questo argomento, ma sono venuti tutti a risultati diversi. mt_rand sembra sempre essere migliore, ma è adatto a questo scopo?

    
posta Zwirbelbart 29.07.2013 - 18:57
fonte

2 risposte

5

Il tuo sale non ha bisogno di essere perfettamente casuale, deve solo essere unico per ciascuno dei tuoi utenti. Vedi questa domanda su Crypto.SE per di più. Ecco perché alcuni siti web usano il nome utente per ricavare il sale da (cioè $salt=$username.$signup_date ).

Nel tuo caso, quando cripta dice "blowfish hash" significa veramente bcrypt così vuoi anche tenere il passo con la legge di Moore quando selezioni il fattore di costo.

Ci sono alcune osservazioni che ho fatto sul tuo codice però. Innanzitutto, strlen() non include il carattere NULL alla fine, quindi strlen($blowfishCharacters) - 1; ti assicura che tu sia " Non vedrò mai un / nel tuo sale. Suggerisco anche di utilizzare range() durante la creazione dell'array, ma questa è la mia preferenza personale. Puoi anche eliminare completamente il ciclo poiché non ci piace reinventare la ruota (giusto?). Pertanto il tuo codice ora si presenta così:

$salt=array_merge(range('a', 'z'), range('A', 'Z'), ['.', '/']); //generate the dictionary
shuffle($salt);
$salt=array_slice($salt, 0, 21); //cut to size

Questo restituirà una matrice $salt con 21 elementi. Il 22esimo elemento richiesto da crypt è in realtà il delimitatore $ .

Per rispondere alla tua domanda originale: in base alla pagina man di mt_rand()

By default, PHP uses the libc random number generator with the rand() function. The mt_rand() function is a drop-in replacement for this. It uses a random number generator with known characteristics using the » Mersenne Twister, which will produce random numbers four times faster than what the average libc rand() provides.

quindi non è più "sicuro" ma funziona più velocemente.

In conclusione, non hai bisogno di un PRF di tipo crypto-grade per ricavare il sale da. Questo perché un sale protegge da tabelle hash pre-calcolate. Se non si dispone di un sale, l'avversario può pre-generare una tabella e confrontarla con l'intero database per trovare una corrispondenza. Il sale fa sì che l'avversario debba eseguire quel processo per ogni voce nel database, rendendo così l'attacco estremamente costoso con un fattore di costo sufficientemente elevato.

Naturalmente l'impostazione del costo troppo alto renderà il tuo server in difficoltà quando molti utenti tenteranno di accedere allo stesso tempo, ma rischierei di scomodare la sicurezza in qualsiasi momento.

Quindi la risposta alla tua domanda è yes mt_rand() è abbastanza buono .

Modifica: questo articolo è una buona guida per l'igiene di bcrypt. Citando la sezione # 2,

A perfect source would be /dev/urandom. Other sources would be mcrypt_create_iv when paired with MCRYPT_DEV_URANDOM. If neither of them are available, you can fall back to openssl_random_pseudo_bytes or mt_rand (at an absolute last resort).

quindi usa mcrypt_create_iv invece .

    
risposta data 29.07.2013 - 19:12
fonte
7

Nella maggior parte delle condizioni, un sale deve essere unico, non crittograficamente imprevedibile.

Quindi in tal caso, sì finché il tuo RNG è correttamente seminato. Un'altra tecnica comune per migliorare la qualità del sale consiste nel concatenare un numero casuale al tempo corrente, quindi un hash (ad esempio SHA1), codificare testualmente (ad esempio base64) e prendere i primi caratteri N . Le probabilità di una collisione sono piuttosto ridotte.

Modifica per spiegare
Ecco una spiegazione di cosa c'è in questa tecnica e perché:

  • L'ora corrente impedisce la ripetizione. Fintanto che due sali non vengono generati contemporaneamente, non saranno uguali a
  • Il numero casuale impedisce la prevedibilità. Non puoi conoscere il sale in anticipo perché c'è un elemento di casualità. Ciò ovviamente presuppone che il numero casuale non sia facilmente prevedibile e non sia basato sul tempo corrente. Ancora più importante, aiuta anche a prevenire le collisioni se due sali vengono generati contemporaneamente.
  • L'hash smussa la distribuzione in modo che ogni bit abbia le stesse possibilità di essere impostato. Inoltre, ti impedisce di sapere cosa è andato a generare il sale semplicemente osservando il risultato.
  • Puoi anche concatenare una stringa segreta con l'input del tuo hash se sei paranoico sulla gente che prevede i valori del sale. Non dovresti avere una ragione per preoccuparti, però.
risposta data 29.07.2013 - 19:07
fonte

Leggi altre domande sui tag