Ho bisogno di generare migliaia (possibilmente milioni) di codici univoci per un cliente. Questi codici possono avere un valore monetario, quindi è vitale che siano VERAMENTE casuali e che nessun modello possa essere individuato e sfruttato da un hacker intelligente.
Ho esaminato varie soluzioni per generare il codice (generato ciclicamente = potrebbe essere indovinato, troppo rischioso, uniqid()
= buono, ma potrei aver bisogno di un codice di lunghezza diversa).
In questo momento sto pensando di generare il codice usando AZ e 0-9 MINUS VOWELS (al fine di garantire che non vengano generate accidentalmente parole maleducate) anche se questo potrebbe essere aumentato in futuro a caratteri minuscoli, ecc.
Finora ho questo (usando una funzione rand personalizzata tratta da qui ):
function generateCode($length = 12) {
$chars = 'BCDFGHJKLMNPQRSTVWXYZ0123456789';
$count = mb_strlen($chars);
for ($i = 0, $result = ''; $i < $length; $i++) {
$randomIndex = devurandom_rand(0, $count - 1);
$result .= mb_substr($chars, $randomIndex, 1);
}
return $result;
}
// CUSTOM RAND FUNCTION
// equiv to rand, mt_rand
// returns int in *closed* interval [$min,$max]
function devurandom_rand($min = 0, $max = 0x7FFFFFFF) {
$diff = $max - $min;
if ($diff < 0 || $diff > 0x7FFFFFFF) {
throw new RuntimeException("Bad range");
}
$bytes = mcrypt_create_iv(4, MCRYPT_DEV_URANDOM);
if ($bytes === false || strlen($bytes) != 4) {
throw new RuntimeException("Unable to get 4 bytes");
}
$ary = unpack("Nint", $bytes);
$val = $ary['int'] & 0x7FFFFFFF; // 32-bit safe
$fp = (float) $val / 2147483647.0; // convert to [0,1]
return round($fp * $diff) + $min;
}
È piuttosto semplice, quindi sono ovviamente preoccupato che non sia abbastanza casuale. Qualcuno può dirmi se questo è un modo decente per garantire che il codice generato sia veramente casuale?
(Nota: ovviamente un hacker di prestigio sarà sempre in grado di tentare un attacco di forza bruta.Tali tentativi saranno gestiti altrove, voglio solo assicurarmi che questo codice sia veramente casuale.)