Questo PHP RNG è sicuro?

0

Ho bisogno di generare una stringa casuale lunga 20 caratteri priva di vocali, e finora ho la seguente funzione per svolgere l'attività.

function random_str()
{
    $i = 1;
    $secret = '';

    while($i==1){
        $str = bin2hex(random_bytes(10));

        $str = preg_replace('/[aeiouAEIOU]|\W+/', '', sha1(microtime() . mt_rand() . $str ));
        $secret .= $str;
        if(strlen($secret) >= 20){
            $i = 0;
        }
    }

    return substr($secret, 0, 20);
}

Questo è sicuro? C'è un modo in cui potrebbe essere migliorato?

Questo non è ancora usato in qualsiasi ambiente dal vivo, ma verrà utilizzato per generare chiavi sia per reimpostare le password sia per visualizzare determinate parti di un sistema che normalmente richiede l'accesso di un utente.

    
posta AntlerFox 08.02.2017 - 11:18
fonte

1 risposta

2

Una pulizia del tuo codice

Questo è lo stesso di quello che stai facendo, ma scritto in modo un po 'più elegante:

function random_str()
{
    $secret = '';
    while(strlen($secret) >= 20) {
       $str = bin2hex(random_bytes(10));
       $str = preg_replace('/[aeiouAEIOU]|\W+/', '', sha1(microtime() . mt_rand() . $str));
       $secret .= $str;
    }
    return substr($secret, 0, 20);
}

Avviso Ho rimosso la variabile $i inutile. (Lo so, non un problema di sicurezza, ma comunque.)

È sicuro?

Il codice è molto contorto e prende un percorso piuttosto strano per risolvere un problema non così difficile. Alcuni problemi:

  • Usi l'hash sha1(microtime() . mt_rand() . $str) quando basti solo su $str sarebbe sufficiente. Ecco dove si ottiene l'input da un CSPRNG. Aggiungendo un po 'di casualità non sicura ( mt_rand ) e il tempo e poi l'hashing non lo migliora.
  • Poiché rimuovi le vocali da una stringa esadecimale, finisci per utilizzare solo il carattere 0123456789bcdf . Quello è solo quattordici - non molto.
  • È un po 'strano generare per prima cosa una stringa contenente caratteri che non vuoi e poi buttarli via, quando puoi generare solo quelli che vuoi.

Alla fine, il risultato è crittograficamente sicuro, poiché si basa su random_bytes() , questo è un CSPRNG. Ma le peculiarità del tuo codice e la tua mancanza di comprensione portano all'insicurezza, ad es. in questo caso potresti finire con meno entropia per personaggio rispetto a quanto ti saresti aspettato.

Un modo migliore per farlo

Usa la funzione PHP random_int per scegliere un carattere da un alfabeto fisso a caso :

function random_string($length, $alphabet) {
    $result = ''; //Initialize an empty string.
    $max = strlen($alphabet) - 1; //The maximum random number we want to generate.
    for($i = 0; $i < $length; $i++) { //Do once for every character in the string.
        $result .= $alphabet[random_int(0, $max)]; //Add a random letter from the alphabet.
    }
    return $result;
}

Probabilmente la performance potrebbe essere migliorata eliminando la concatenazione di stringhe nel loop, ma probabilmente non è un grosso problema.

    
risposta data 08.02.2017 - 12:51
fonte

Leggi altre domande sui tag