2010-03-25 22 views
12

¿Cuál es la mejor forma de generar una sal criptográficamente segura de 32 bytes en PHP, sin depender de las bibliotecas que rara vez se incluyen en las instalaciones típicas de PHP?Generando una sal en PHP

Después de googlear descubrí que mt_rand no se considera lo suficientemente seguro, pero no he encontrado una sugerencia para un reemplazo. Un artículo sugirió leer desde /dev/random pero no solo esto no funcionará en Windows; también es muy lento.

Quiero un equilibrio razonable entre la seguridad y la velocidad (es decir, no se debe tomar 20 segundos para generar 512 bytes, como suele hacer /dev/random)

+2

'/ dev/urandom' se puede utilizar para una generación más rápida, pero aún no funcionará en los sistemas Windows. – Amber

Respuesta

7

Nota: mcrypt ya no se utiliza en PHP 7.1. Skip to the up-to-date answer.

Es posible que desee echar un vistazo a la documentación (y comentarios) para mcrypt_create_iv().

+1

mcrypt está en desuso en PHP 7.1. No debe escribir código que ya está en desuso. Entonces, si leen esto en 2016, no utilicen esta respuesta, prefieran la de @Scott Arciszewski. – JesusTheHun

-9

Creo microtime() es suficiente.

Extrañamente, pero todavía estoy recibiendo votos abajo para esta respuesta.

Aunque la única explicación que tengo es que la microtime es predecible.
Suena extraño para mí ya que salt siempre asumió como abiertamente conocido - por lo tanto, no hay ningún uso para la predicción en absoluto.

+1

No realmente. No solo es muy fácil de predecir (es la hora actual), sino que tampoco puedo obtener 32 bytes de él. – qster

+4

@qster puede usarlo como generador de números aleatorios. Y obtenga cualquier cantidad de bytes que desee. Y no es la hora actual, la estropeaste con el tiempo(). Los microsegundos cambian bastante rápido. Y es solo sal, no necesita demasiada seguridad con la sal. –

+0

@YourCommonSense Ejecute 'echo microtime()' a través de un ciclo for (10 loops está bien) y vea qué tan mal está ... –

-3

uniqid() debería estar bien para este propósito.

+1

Uso uniqid() con algún valor de inicialización rápidamente computable (como el microtempo sugerido), también. No he hecho un análisis criptográfico, pero parece ajustarse a la factura. – Boldewyn

0

Lea de /dev/urandom, o use openssl_random_pseudo_bytes().

7

Nota: mcrypt ya no se utiliza en PHP 7.1. Skip to the up-to-date answer.

Puede usar la función mycrypt_create_iv(), ya que la versión 5.3 de PHP también utiliza la fuente aleatoria en un servidor de Windows (no solo en Unix). Antes de usarlo, debe verificar si se define la constante MCRYPT_DEV_URANDOM.

mcrypt_create_iv($length, MCRYPT_DEV_URANDOM); 

A diferencia del azar, urandom no bloquea el servidor, si no hay suficiente entropía disponible. Dado que la contraseña debe ser única (no necesariamente aleatoria), urandom parece ser una buena opción para mí.

+0

Tenga en cuenta que el segundo argumento es opcional y el valor 'MCRYPT_DEV_URANDOM' es el predeterminado, por lo que si no desea cambiarlo, puede hacer' mcrypt_create_iv ($ length) '. Además, esta característica se implementa en la extensión 'mcrypt' que puede o no estar instalada en su servidor. Por último, el resultado de esa función es una cadena binaria que a menudo no es lo que necesita, ya que desea guardar la sal para hacer referencia más adelante. Normalmente 'base64_encode' el resultado antes de usarlo como sal. – Guss

+0

@Guss: estos son buenos puntos. Además, uno debe verificar, de qué forma se espera la sal. BCrypt, por ejemplo, no aceptará una sal binaria, pero una sal codificada en base64 tampoco es válida. Para el hash de contraseñas, es mejor utilizar la función integrada [password_hash()] (http://www.php.net/manual/en/function.password-hash.php), que genera una sal segura por sí mismo. – martinstoeckli

+0

Una razón para no usar 'password_hash()' es que no estoy implementando una contraseña. Necesito una sal para implementar un protocolo de autorización de estilo "api key" sin estado. – Guss

2

uniqueid no se adapta bien para generar una cadena aleatoria ya que también es microtime base. Un Ciclo de CPU generalmente es mucho más corto que una tilde de microtime, lo que puede conducir a la posible constancia de una variable dada dentro de los bucles. Ajuste del segundo parámetro "entropía" true,

uniqid('', true) 

proporcionará una mayor aleatoriedad.

para obtener una cadena aleatoria que es también compatible con la mayoría de caracteres conjuntos, se puede aplicar la codificación base64 a la mcrypt initilization función vectorial mcrypt_create_iv:

$length = 16; 
base64_encode(mcrypt_create_iv(ceil(0.75*$length), MCRYPT_DEV_URANDOM)) 
//> hlZuRJypdHFQPtI2oSFrgA== 
strlen(base64_encode(mcrypt_create_iv(ceil(0.75*$length), MCRYPT_DEV_URANDOM))) 
//> 16 

Reducir el personaje-alfabeto a 2^6bit aumenta el tamaño, que se explica anteriormente.