¿Es mt_rand () adecuado para generar una sal?

3

Se supone que tengo que seguir el código para generar una sal de pez globo al azar para guardar una nueva contraseña:

$blowfishCharacters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./';
$salt = '';
$type = '2a';
$cost = '08';

$maxIndex = strlen($blowfishCharacters) - 1;

for ($i = 0; $i < 22; $i++) {
        $salt .= $blowfishCharacters[mt_rand(0, $maxIndex)];
}

$salt = '$' . $type . '$' . $cost . '$' . $salt;
$pass = crypt($password, $salt);

Leí varias discusiones sobre este tema, pero todas obtuvieron resultados diferentes. mt_rand siempre parece ser mejor, pero ¿es adecuado para este propósito?

    
pregunta Zwirbelbart 29.07.2013 - 18:57
fuente

2 respuestas

5

Su sal no necesita ser perfectamente aleatoria, solo necesita ser única para cada uno de sus usuarios. Consulte esta pregunta en Crypto.SE para más. Es por eso que algunos sitios web usan el nombre de usuario para derivar la sal (es decir, $salt=$username.$signup_date ).

En tu caso, cuando crypt dice 'blowfish hash' realmente significa bcrypt así que También desea mantenerse al día con la ley de Moore al seleccionar el factor de costo.

Sin embargo, hay algunas observaciones que hice en tu código. Primero, strlen() no incluye el carácter NULL al final, por lo que strlen($blowfishCharacters) - 1; se asegura de que ' Nunca veré un / en tu sal. También sugeriría usar range() al crear la matriz, pero esa es mi preferencia personal. También puede eliminar completamente el bucle, ya que no nos gusta reinventar la rueda (¿verdad?). Por lo tanto, su código ahora se ve así:

$salt=array_merge(range('a', 'z'), range('A', 'Z'), ['.', '/']); //generate the dictionary
shuffle($salt);
$salt=array_slice($salt, 0, 21); //cut to size

Esto devolverá una matriz $salt con 21 elementos. El elemento 22 requerido por crypt es en realidad el delimitador $ .

Para responder a su pregunta original: de acuerdo con página de manual de mt_rand() '

  

Por defecto, PHP usa el generador de números aleatorios libc con la función rand (). La función mt_rand () es un reemplazo directo para esto. Utiliza un generador de números aleatorios con características conocidas usando el »Mersenne Twister , que producirá números aleatorios cuatro veces más rápido de lo que proporciona el promedio libc rand ().

para que no sea más "seguro", solo se ejecuta más rápido.

En conclusión, usted no necesita un PRF criptográfico para obtener la sal. Eso es porque una sal protege contra las tablas hash pre-computadas. Si no tiene un salt, el adversario puede generar una tabla antes y compararla con toda su base de datos para encontrar una coincidencia. La sal se asegura de que el adversario tenga que hacer ese proceso para cada entrada en la base de datos, lo que hace que el ataque sea extremadamente costoso con un factor de costo suficientemente alto.

Por supuesto, establecer el costo demasiado hará que su servidor tenga dificultades cuando muchos usuarios intentan iniciar sesión al mismo tiempo, pero en cualquier momento cambiaría el riesgo de inconvenientes por seguridad.

Entonces, la respuesta a tu pregunta es yes mt_rand() es suficiente .

Editar: Este artículo es una buena guía sobre la higiene de cripto. Citando la sección # 2,

  

Una fuente perfecta sería / dev / urandom. Otras fuentes serían mcrypt_create_iv cuando se emparejan con MCRYPT_DEV_URANDOM. Si ninguno de ellos está disponible, puede recurrir a openssl_random_pseudo_bytes o mt_rand (como último recurso).

así que use mcrypt_create_iv en su lugar .

    
respondido por el rath 29.07.2013 - 19:12
fuente
7

En la mayoría de las condiciones, una sal solo necesita ser única, no criptográficamente impredecible.

Entonces, en ese caso, sí, siempre y cuando tu RNG esté correctamente sembrado. Otra técnica común para mejorar la calidad de la sal es concatenar un número aleatorio a la hora actual, luego codificar ese (por ejemplo, SHA1), codificar textualmente (por ejemplo, base64) y tomar los primeros caracteres N . Las posibilidades de colisión son bastante escasas.

Editar para explicar
Aquí hay una explicación de lo que está en esta técnica y por qué:

  • La hora actual impide la repetición. Mientras dos sales no se generen al mismo tiempo, no serán las mismas
  • El número aleatorio evita la previsibilidad. No se puede saber la sal antes de tiempo porque hay un elemento de aleatoriedad. Obviamente, esto supone que el número aleatorio no es fácilmente predecible y no se basa en la hora actual. Más importante aún, también ayuda a prevenir colisiones si se generan dos sales al mismo tiempo.
  • El hash suaviza la distribución para que cada bit tenga las mismas posibilidades de establecerse. También evita que sepas qué se generó la sal con solo mirar el resultado.
  • También puede concatenar una cadena secreta a la entrada de su hash si está paranoico acerca de las personas que predicen los valores de sal. Sin embargo, no debes tener una razón para preocuparte.
respondido por el tylerl 29.07.2013 - 19:07
fuente

Lea otras preguntas en las etiquetas