¿Qué tiene de bueno / malo este hashing de contraseña personalizado?

2

Para el registro, esto fue solo para fines de aprendizaje, se me ha dicho que ni siquiera lo use para un sitio web personal que no espero que nadie visite, por lo que este post es, desafortunadamente, el último que veré de este código. Sin embargo, he hecho todas las cosas sobre las que leo y me parecen decentes (pero no soy un experto), así que tengo curiosidad por saber qué partes podrían ser lo suficientemente malas como para que la recomendación para todos sea nunca ¿Alguna vez usó una solución personalizada?
No nombro a nadie, pero estoy bastante seguro de que ya he hecho un trabajo mucho mejor que el host web gratuito que comienza con un número triple jaja, mi contraseña de texto simple fue robada desde allí.

Aquí está la idea básica de lo que hice:

Salt and IV
Cada sal se genera mediante una función aleatoria pero no criptográficamente segura en PHP (aunque es mejor que el valor aleatorio predeterminado). Luego se encripta con blowfish usando una clave definida en el código y una IV definida en un archivo real (que está protegido por htaccess). El valor cifrado se almacena, por lo que es muy fácil cambiar la clave de IV o sal para invalidar todas las contraseñas. Además, si la base de datos está en peligro, las sales aún no se pueden descifrar sin tener acceso al sistema de archivos.

Hash
Utiliza el estiramiento de teclas y sha512. La cantidad de estiramiento de la clave se define mediante un módulo de un valor crc32 de la contraseña y la sal, por lo que cada usuario tiene una cantidad diferente, y puede cambiar el valor para permitir tiempos de procesamiento más largos. Cada hash de repetición utiliza algunos hashes dentro de él para intentar mantenerlo bastante aleatorio.

Aquí está el código real que tengo, si no sabes PHP todavía es bastante fácil ver lo que sucede en línea por línea:

$salt_key = 'íSgüý[Îaí²zÿCV™F÷œDDa©^fU©êm‹“.Ù   ®Kâ³ÃX}rÿ,¢\ˆÿ7L³¢QÆH’YeTsÙõŸ¥éÙí#W—c´VÆ';

function get_iv(){
    // It stores it as a file, but there's no point showing that part so here's the actual code bit
    return mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC), MCRYPT_RAND);
}

function generate_salt(){
    global $salt_key;
    $salt = substr(uniqid(mt_rand(), true), 0, 32);
    $key = hash('sha256', $salt_key, true);
    $iv = get_iv();
    $encrypt = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $salt, MCRYPT_MODE_CFB, $iv);
    return array($salt, $encrypt);
}

function decrypt_salt($encrypted){
    global $salt_key;
    $key = hash('sha256', $salt_key, true);
    $iv = get_iv();
    return mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $encrypted, MCRYPT_MODE_CFB, $iv);
}

function hash_password($password, $salt){
    #return hash('sha512', $password.$salt, true);
    $hash = $salt;
    for($i=0; $i<(crc32($salt.$password) % 129197); $i++){
        $hash = hash('sha512', $hash.$password.$salt.hash('sha512', $salt.$hash.$password).md5($salt.md5($password.$hash)), true);
    }
    return $hash;
}

La parte para verificar si la contraseña es válida, básicamente solo compara el hash nuevo con el anterior, así que lo dejé fuera. El único inconveniente basado en las cosas que he leído que debería hacer un buen algoritmo es que no utiliza mucha memoria.

    
pregunta Peter 13.10.2016 - 18:11
fuente

2 respuestas

4

Preguntas abiertas:

  • ¿Por qué no está utilizando un RNG criptográficamente seguro para la sal? No los va a generar con tanta frecuencia como para correr el riesgo de agotar el grupo de entropía del sistema en un sistema moderno.
  • ¿Cómo se generó su clave de cifrado de sal?
  • ¿Cuánto tiempo dura tu salt_key (antes de que lo trates)?
  • ¿Por qué hash de tu salt_key ? Eso no agrega seguridad.
  • ¿Por qué el hashing anidado demasiado complicado (incluido el uso de MD5 , de todas las cosas) en su ciclo de estiramiento de teclas? Me recuerda a Comentario de Moxie Marlinspike sobre el esquema MS-CHAP v2 (roto) (busque la cadena" complejidad innecesaria ").

Problemas notables:

  • De hecho, usted quiere usar sales aleatorias seguras (y IV). Importa cuán predecible es la sal; Las sales predecibles permiten a los atacantes preprogramar tablas de búsqueda para las sales predichas contra contraseñas probables. Las IV predecibles probablemente sean un riesgo menor en este contexto, pero no hay razón para que no se utilicen de forma segura y aleatoria.
  • Su algoritmo de iteración de estiramiento de clave proporciona poco o ningún aumento en la seguridad: para cada contraseña de prueba, el atacante puede calcular el recuento de iteraciones bien, suponiendo que conocen la sal (y si no lo hacen, no pueden trate de forzar con fuerza bruta el verificador de contraseñas) y lo pone en riesgo de ejecutar muchas menos vueltas de hash de las que desea. En particular, si el CRC es un múltiplo exacto de 127197, la sal del usuario se almacena como su verificador de contraseña y la contraseña no se utiliza en absoluto, por lo que ¡cualquier contraseña funcionará para ese usuario! Si obtienes un millón de usuarios, alrededor de 8 de ellos no tendrán protección de contraseña .
  • No tiene ningún método para rotar o actualizar el algoritmo para la verificación de la contraseña, al menos nada visible en lo que se presenta aquí. Es posible que los atributos críticos codificados (como la clave, las primitivas criptográficas y la forma en que se determina el conteo de iteración) deban cambiar en algún momento en el futuro, momento en el cual deberá poder verificar la contraseña de un usuario según el esquema anterior antes de generar un nuevo verificador de contraseñas con el nuevo esquema (a menos que solo planee obligar a todos a restablecer su contraseña, lo cual es una molestia y solo debe hacerse cuando exista una razón para esperar que las anteriores se vean comprometidas). Por lo tanto, necesita una forma de especificar una versión del algoritmo de verificación de contraseña, o al menos necesita almacenar identificadores (probablemente índices) para sus diversos valores constantes actualmente, y buscar los valores según el identificador / índice de la versión almacenada de cada usuario.
  • En el peor de los casos, 129 + k iteraciones de SHA-512 (no importa, SHA512 (SHA512 (MD5 (MD5))) va a tomar mucho tiempo en su servidor. Un atacante que encuentra una combinación de nombre de usuario y contraseña para los que es tan costoso calcular el verificador puede simplemente enviar un montón de solicitudes con credenciales como esa (especialmente porque, debido a la reversibilidad del CRC, el atacante puede manipular la entrada para obtener exactamente la suma de comprobación deseada). Eso probablemente causará una denegación de servicio en su servidor. Los factores de trabajo para la verificación de la contraseña deben ser lo suficientemente altos para reducir la fuerza bruta, pero no deben ser lo suficientemente altos como para que un atacante pueda sobrecargar un servidor.
respondido por el CBHacking 14.10.2016 - 03:23
fuente
1

Algo malo de esto es que es complicado, y cualquier desarrollador que se una al proyecto no podrá saber fácilmente si es seguro a menos que se tome el tiempo de leerlo y entenderlo. Si les importa la seguridad y la calidad del sistema en general, pueden sentirse motivados a tomarse ese tiempo, incluso si no es necesario para sus tareas inmediatas.

La solución simple, en PHP 5.5 o posterior, es usar solo el password_hash y password_verify .

    
respondido por el bdsl 15.03.2018 - 23:11
fuente

Lea otras preguntas en las etiquetas