Generando un token no descargable para correos electrónicos de confirmación

13

Estoy generando un token para usar al hacer clic en el enlace en un correo electrónico de verificación. Planeo usar uniqid () pero la salida será predecible permitiendo que un atacante omita la confirmación e correos Mi solución es hachíslo. Pero eso no es suficiente porque si se descubre el hash que estoy usando, entonces será predecible. La solución es saltearlo. No estoy seguro de cómo hacerlo porque si uso una función para dar sal variable (por ejemplo, en pseudocódigo hash(uniqid()+time()) ), ¿no está garantizada la singularidad del hash? Debería usar un hash constante y eso sería suficiente (por ejemplo, hash(uniqid()+asd741) )

Creo que todas las respuestas pierden un punto importante. Tiene que ser único. ¿Qué sucede si openssl_random_pseudo_bytes() produce el mismo número dos veces? Entonces un usuario no podría activar su cuenta. ¿Es el argumento contrario de la gente que es poco probable que produzca el mismo número dos veces? Por eso estaba considerando uniqid() porque su salida es única.

Supongo que podría usar ambos y agregarlos juntos.

    
pregunta Celeritas 08.08.2013 - 22:53
fuente

4 respuestas

25

Deseas aleatoriedad indiscutible. Luego, usa aleatoriedad indiscutible. Utilice openssl_random_pseudo_bytes() que se conectará al local PRNG criptográficamente fuerte . No utilice rand() o mt_rand() , ya que son predecibles ( mt_rand() es estadísticamente bueno pero no es válido contra atacantes sensibles). No se comprometa, use un buen PRNG. No intente hacer algo usted mismo lanzando la función hash y similares; solo el dolor se encuentra al final de este camino.

Genere 16 bytes, luego codifíquelos en una cadena si necesita una cadena. bin2hex() codifica en hexadecimal; 16 bytes se convierten en 32 caracteres. base64_encode() codifica en Base64; 16 bytes se convierten en 24 caracteres (los últimos dos son signos '=').

16 bytes son 128 bits, ese es el "valor seguro", lo que hace que las colisiones sean tan improbables que no debes preocuparte por ellas. No vayas por debajo de eso a menos que tengas una buena razón (y, aun así, no vayas por debajo de 16).

    
respondido por el Tom Leek 08.08.2013 - 23:11
fuente
16

Asegúrate de tener soporte de OpenSSL , y nunca te equivocarás con esta herramienta de una sola línea

$token = bin2hex(openssl_random_pseudo_bytes(16));
    
respondido por el Adi 08.08.2013 - 23:05
fuente
1

En PHP 7, puedes usar random_bytes :

  

Genera una cadena de longitud arbitraria de bytes aleatorios criptográficos que son adecuados para el uso criptográfico, como cuando se generan sales, claves o vectores de inicialización.

Entonces, para generar un token hexadecimal de 16 bytes, harías:

$token = bin2hex(random_bytes(16));

Formalmente, no hay garantía de que todos los números sean únicos. Pero es tan poco probable que ocurra una colisión que será mejor que te preocupes por ser golpeado por un meterorite.

    
respondido por el Anders 14.11.2018 - 16:39
fuente
-1

Esta es la función que uso para generar un token aleatorio en PHP:

<?php
function generateToken($length = 24) {
        if(function_exists('openssl_random_pseudo_bytes')) {
            $token = base64_encode(openssl_random_pseudo_bytes($length, $strong));
            if($strong == TRUE)
                return strtr(substr($token, 0, $length), '+/=', '-_,'); //base64 is about 33% longer, so we need to truncate the result
        }

        //fallback to mt_rand if php < 5.3 or no openssl available
        $characters = '0123456789';
        $characters .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/+'; 
        $charactersLength = strlen($characters)-1;
        $token = '';

        //select some random characters
        for ($i = 0; $i < $length; $i++) {
            $token .= $characters[mt_rand(0, $charactersLength)];
        }        

        return $token;
}
?>
    
respondido por el Techbrunch 08.08.2013 - 23:02
fuente

Lea otras preguntas en las etiquetas