php - hackear - como robar wifi
Generando un código único de 6 dígitos (6)
como Baba dijo que generar una cuerda sobre la marcha provocará toneladas de colisiones. cuanto más cerca vaya a 80 millones ya generados, más difícil será obtener una cadena disponible
Otra solución podría ser generar todas las combinaciones posibles una vez, y almacenar cada una de ellas en la base de datos, con algún campo de columna booleana que marque si una fila / símbolo ya está usado o no.
entonces para obtener uno de ellos
SELECT * FROM tokens WHERE tokenIsUsed = 0 ORDER BY RAND() LIMIT 0,1
y luego marcarlo como ya se usó
UPDATE tokens SET tokenIsUsed = 1 WHERE token = ...
Estoy generando un código de 6 dígitos de los siguientes caracteres. Estos se usarán para sellar pegatinas.
Se generarán en lotes de 10k o menos (antes de la impresión) y no creo que haya más de 1 o 2 millones en total (probablemente mucho menos).
Después de generar los lotes de códigos, revisaré la base de datos MySQL de los códigos existentes para asegurarme de que no haya duplicados.
// exclude problem chars: B8G6I1l0OQDS5Z2
$characters = ''ACEFHJKMNPRTUVWXY4937'';
$string = '''';
for ($i = 0; $i < 6; $i++) {
$string .= $characters[rand(0, strlen($characters) - 1)];
}
return $string;
- ¿Es este un enfoque sólido para generar el código?
- ¿Cuántas permutaciones posibles habría? (Código de 6 dígitos del grupo de 21 caracteres). Lo siento, la matemática no es mi punto fuerte
Tuve el mismo problema y encontré una solución de código abierto muy impresionante:
Puedes tomarlo y usarlo, también vale la pena mirar en su código fuente para entender lo que sucede debajo del capó.
21 ^ 6 = 85766121 posibilidades.
Usar un DB y almacenar valores usados es malo. Si quieres simular la aleatoriedad, puedes usar lo siguiente:
Reduzca a 19 números posibles y haga uso del hecho de que los grupos de orden p ^ k donde p es un primo impar siempre son cíclicos.
Tome el grupo de orden 7 ^ 19, usando un generador de co-prime a 7 ^ 19 (escogeré 13 ^ 11, puede elegir cualquier cosa que no sea divisible por 7).
Entonces, lo siguiente funciona:
$previous = 0;
function generator($previous)
{
$generator = pow(13,11);
$modulus = pow(7,19); //int might be too small
$possibleChars = "ACEFHJKMNPRTUVWXY49";
$previous = ($previous + $generator) % $modulus;
$output='''';
$temp = $previous;
for($i = 0; $i < 6; $i++) {
$output += $possibleChars[$temp % 19];
$temp = $temp / 19;
}
return $output;
}
Recorrerá todos los valores posibles y se verá un poco aleatorio a menos que vaya a cavar. Una alternativa aún más segura serían los grupos multiplicativos, pero ya olvidé mi matemática :(
O ... puedes codificar el nombre de usuario + datetime en md5 y guardarlo en la base de datos, esto seguro generará un código único;)
¡Tendría 21 ^ 6 códigos = 85 766 121 ~ 85.8 millones de códigos!
Para generarlos todos (lo que llevaría algún tiempo), observe la respuesta seleccionada a esta pregunta: algoritmo que tomará números o palabras y encontrará todas las combinaciones posibles .
- Hay una gran cantidad de combinaciones posibles con o sin repetición, por lo que su lógica sería suficiente
- La colisión sería frecuente porque estás usando
rand
see str_shuffle y randomness . - Cambiar
rand
amt_rand
- Use almacenamiento rápido como
memcached
oredis
no MySQL al verificar
Posibilidad total
21 ^ 6 = 85,766,121
85,766,121
debería estar bien. Para agregar una base de datos a esta generación, intente:
Ejemplo
$prifix = "stamp.";
$cache = new Memcache();
$cache->addserver("127.0.0.1");
$stamp = myRand(6);
while($cache->get($prifix . $stamp)) {
$stamp = myRand(6);
}
echo $stamp;
Función utilizada
function myRand($no, $str = "", $chr = ''ACEFHJKMNPRTUVWXY4937'') {
$length = strlen($chr);
while($no --) {
$str .= $chr{mt_rand(0, $length- 1)};
}
return $str;
}