w3schools uniqid unico rand number make generate crear php security hash random passwords

php - unico - md5(uniqid) tiene sentido para tokens únicos aleatorios?



uniqid php function (8)

Quiero crear un generador de tokens que genere tokens que el usuario no pueda adivinar y que sigan siendo únicos (se utilizarán para restablecer contraseñas y códigos de confirmación).

A menudo veo este código; ¿tiene sentido?

md5(uniqid(rand(), true));

De acuerdo con un comment uniqid($prefix, $moreEntopy = true) yields

primeros 8 caracteres hexadecimales = Unixtime, últimos 5 caracteres hexadecimales = microsegundos.

No sé cómo se maneja el parámetro $prefix .

Entonces, si no establece el indicador $ moreEntopy como verdadero, arroja un resultado predecible.

PREGUNTA: Pero si usamos uniqid con $moreEntopy , ¿qué nos permite comprar hash con md5? Es mejor que:

md5(mt_rand())

edit1: Almacenaré este token en una columna de base de datos con un índice único, por lo que detectaré columnas. Podría ser de interés /


Definir "único". Si quiere decir que dos tokens no pueden tener el mismo valor, el hashing no es suficiente: debe respaldarse con una prueba de exclusividad. El hecho de que suministre el algoritmo hash con entradas únicas no garantiza salidas únicas.


Esta es una copia de otra pregunta que encontré que se le preguntó unos meses antes de esta. Aquí hay un enlace a la pregunta y mi respuesta: https://.com/a/13733588/1698153 .

No estoy de acuerdo con la respuesta aceptada. Según el propio sitio web de PHP "[uniqid] does not generate cryptographically secure tokens, in fact without being passed any additional parameters the return value is little different from microtime(). If you need to generate cryptographically secure tokens use openssl_random_pseudo_bytes()."

No creo que la respuesta sea más clara que esto, uniqid no es seguro.


MD5 es un algoritmo decente para producir ID dependientes de datos . Pero en caso de que tenga más de un elemento que tenga el mismo flujo de bits (contenido), estará produciendo dos ID "MD5" similares.

Entonces, si solo lo aplica a una función rand() , que garantiza que no creará el mismo número dos veces, estará bastante seguro.

Pero para una distribución más fuerte de las claves, personalmente usaría SHA1 o SHAx, etc. ... pero aún tendrá el problema de que datos similares conducen a claves similares.


Me encontré con una idea interesante hace un par de años.
Se almacenan dos valores hash en la base de datos, uno generado con md5 ($ a) y el otro con sha ($ a). Luego chek si ambos valores son corect. El punto es que si el atacante rompió tu md5 (), no puede romper tu md5 AND sha en el futuro cercano.
El problema es: ¿cómo se puede usar ese concepto con la generación de tokens necesaria para su problema?


Para responder a su pregunta, el problema es que no puede tener un generador que esté garantizado al azar y único como aleatorio por sí mismo, es decir, md5(mt_rand()) puede generar duplicados. Lo que quiere es valores únicos de "aparición aleatoria". uniqid proporciona la identificación única, rand () afijos un número aleatorio que hace que sea aún más difícil de adivinar, md5 enmascara el resultado para hacerlo aún más difícil de adivinar. Nada es indescifrable Solo tenemos que hacerlo tan difícil que ni siquiera querrían intentarlo.


Primero, el alcance de este tipo de procedimiento es crear una clave / código hash /, que será único para una base de datos determinada. Es imposible crear algo único para todo el mundo en un momento dado. Una vez dicho esto, debe crear una cadena simple y visible, utilizando un alfabeto personalizado, y verificar el código creado contra su base de datos (tabla). Si esa cadena es única, entonces aplica un md5() a ella y no puede ser adivinada por nadie ni por ninguna secuencia de comandos. Sé que si profundizas en la teoría de la generación criptográfica puedes encontrar muchas explicaciones sobre este tipo de generación de código, pero cuando lo pones en práctica no es tan complicado.

Aquí está el código que uso para generar un código único simple de 10 dígitos.

$alphabet = "aA1!bB2@cC3#dD5%eE6^fF7&gG8*hH9(iI0)jJ4-kK=+lL[mM]nN{oO}pP/qQ/rR,sS.tT?uUvV>xX~yY|zZ`wW$"; $code = ''''; $alplhaLenght = strlen($alphabet )-1; for ($i = 1; $i <= 10; $i++) { $n = rand(1, $alplhaLenght ); $code .= $alphabet [$n]; }

Y aquí hay algunos códigos generados, aunque puede ejecutarlo usted mismo para ver cómo funciona:

SpQ0T0tyO%
Uwn [MU] [.
D | [ROt + Cd @
O6I | w38TRe

Por supuesto, puede haber muchas "mejoras" que se pueden aplicar a él, para hacerlo más "complicado", pero si aplica un md5() a esto, se convertirá en, digamos "indescifrable". :)


Sé que la pregunta es antigua, pero aparece en Google, así que ...

Como dijeron otros, rand() , mt_rand() o uniqid() no le garantizarán su unicidad ... incluso no se debería usar openssl_random_pseudo_bytes() , ya que usa las características obsoletas de OpenSSL .

Lo que debe usar para generar hash aleatorio (igual que md5) es random_bytes() (introducido en PHP7). Para generar hash con la misma longitud que MD5:

bin2hex(random_bytes(16));

Si está utilizando PHP 5.x puede obtener esta función incluyendo la biblioteca random_compat .


rand () es un peligro para la seguridad y nunca debe usarse para generar un token de seguridad: rand () vs mt_rand () (Mire las imágenes "estáticas"). Pero ninguno de estos métodos para generar números aleatorios es criptográficamente seguro. Para generar datos seguros, una aplicación necesitará acceder a un CSPRNG proporcionado por la plataforma, el sistema operativo o el módulo de hardware.

En una aplicación web, una buena fuente de secretos seguros es el acceso no bloqueante a un conjunto de entropía como /dev/urandom . A partir de PHP 5.3, las aplicaciones PHP pueden usar openssl_random_pseudo_bytes() , y la biblioteca Openssl elegirá la mejor fuente de entropía basada en su sistema operativo, bajo Linux esto significa que la aplicación usará /dev/urandom . Este fragmento de código de Scott es bastante bueno :

function crypto_rand_secure($min, $max) { $range = $max - $min; if ($range < 0) return $min; // not so random... $log = log($range, 2); $bytes = (int) ($log / 8) + 1; // length in bytes $bits = (int) $log + 1; // length in bits $filter = (int) (1 << $bits) - 1; // set all lower bits to 1 do { $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes))); $rnd = $rnd & $filter; // discard irrelevant bits } while ($rnd >= $range); return $min + $rnd; } function getToken($length=32){ $token = ""; $codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; $codeAlphabet.= "abcdefghijklmnopqrstuvwxyz"; $codeAlphabet.= "0123456789"; for($i=0;$i<$length;$i++){ $token .= $codeAlphabet[crypto_rand_secure(0,strlen($codeAlphabet))]; } return $token; }