¿Cómo es posible que te identifique?

Iniciado por Zarlok, 22 Agosto 2014, 19:04 PM

0 Miembros y 1 Visitante están viendo este tema.

Zarlok

Hola, he estado buscando por Internet una forma de poder estar tranquilo al cifrar las contraseñas en la BD para que nadie las pueda descifrar.

En la mayoría de sitios recomiendan que en la BD haya un campo para el salt y otra para la contraseña que se la habrá aplicado un sha256 u otro.

Pero en otro lugar han afirmado que es muy inseguro y que lo mejor es usar bcrypt, en el que por lo que veo no hace falta que haya ningún campo salt en la bd y funciona de la siguiente manera:

Cómo podéis ver en la imagen se entiende bien, excepto que no logro entender a la hora de identificarte:
if (crypt('password_introducida',$passwordEnBD) == $passwordEnBD) CORRECTO

¿Cómo puede ser? En principio siempre que te registres ni que sea con la misma pass, cómo el salt cada vez es distinto, $passwordEnBD será diferente. ¿Pero claro, si no guardas el salt en la bd, cómo puedes identificarte? Lo he probado tal cómo la imagen y funciona perfectamente, pero no entiendo cómo lo identifica.

¿Alguien que lo sepa, me lo podría explicar? Gracias.




#!drvy

#1
El código que expones no puede devolver true, te falla algo o no incluyes todos los detalles.

Código (php) [Seleccionar]
$pdb = '$2a$07$yMoJrJpwEPrmVnZx4KIyNuOAiOMQksjkV1EW0YRgVe33eYe/yT60y';
$pdg = crypt('micontraseña',$pdb);

echo $pdb,PHP_EOL,$pdg,PHP_EOL;
var_dump(($pdg==$pdb));


Resultado
Código (log) [Seleccionar]
$2a$07$yMoJrJpwEPrmVnZx4KIyNuOAiOMQksjkV1EW0YRgVe33eYe/yT60y
$2a$07$yMoJrJpwEPrmVnZx4KIyNu0VIclLyka7I/M.Wee2RHTZS2YZUlEpy
bool(false)


Sin embargo, si, se hace un mal uso... y dependiendo de la versión de PHP, igual puede llegar a coincidir. En este caso se hace mal uso porque suministras como salt el código generado previamente y usas ese mismo código para hacer la comprobación..




Siempre haz de dar un uso correcto de crypt(). Ademas, debes asegurarte de que el salt es seguro y aleatorio.

http://php.net/manual/en/function.crypt.php

Ejemplo de blowfish.
Código (php) [Seleccionar]
$password = 'micontraseña';
$salt = substr(md5(rand(1000,9999).rand(1000,9999)),0,22);
$hash = crypt($password,'$2y$07$'.$salt.'$');
//$2a$07$b5abbc0b1842efadeec68uyB3irC.LfyTkWhkJwbMmD0SymXmsfrO





CitarPero en otro lugar han afirmado que es muy inseguro y que lo mejor es usar bcrypt

El uso de algoritmos tipo bcrypt se considera "mas seguro", porque a diferencia de algoritmos como md5,sha1,sha512 etc.. blowfish esta hecho para tardar. Tiene lo que se llama factor de dificultad.

Para que veas la diferencia BLOWFISH 2Y vs SHA512 (los dos con el mismo salt)
Código (php) [Seleccionar]
$time = microtime(true);
$hash1 = crypt($password,'$2y$12$'.$salt.'$');
echo 'Blowfish: ',(microtime(true)-$time),PHP_EOL;

$time = microtime(true);
$hash2 = crypt($password,'$6$'.$salt);
echo 'SHA512: ',(microtime(true)-$time),PHP_EOL;


Resultado
Código (log) [Seleccionar]
Blowfish: 0.32424879074097
SHA512:   0.0095410346984863


La idea es que el algoritmo tarda mas en generar la llave y por tanto aumenta significativamente el tiempo que tomaría realizar un ataque de fuerza bruta. No importa cual grande es SHA512 o SHA256.. si están hechos para velocidad (fueron pensados para comprobar la consistencia de archivos, no para hashear contraseñas xD), no se les considera aptos para este trabajo.

Como nota, dejare que crypt() para SHA256 y SHA512 soporta el parámetro rounds dentro del salt. El valor por defecto es de 5000 (con el que fue hecho el ejemplo).. haría falta ponerlo en mas de 100.000 para que alcance el  factor de dificultad 12 de BLOWFISH xD.

Código (php) [Seleccionar]
crypt($password,'$6$rounds=150000$'.$salt);


PD: Temas sobre PHP van al subforo de PHP.

PD2: Siempre usa === para comparar strings.

Saludos

Zarlok

#2
Hola,

Uso la versión PHP Version 5.4.27.

También he probado el código y a mi si me devuelve true. Ahora lo pongo más detallado:

Código (php) [Seleccionar]

//Este código lo tengo cuando se registar un usuario

function crypt_blowfish_bydinvaders($password, $digito = 7) {
   //este set_salt sirve para que después coja un caracter aleatoriamente (hasta 22)
   $set_salt = './1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
   $salt = sprintf('$2y$%02d$', $digito);
   for($i = 0; $i < 22; $i++)
   {
       $salt .= $set_salt[mt_rand(0, 63)];
   }
   return crypt($password, $salt);
}

//llamada a la funcion pasando por post la pass (he puesto la pass más segura actualmente xd... para que se vea mejor)
$passwordCrypt = crypt_blowfish_bydinvaders('123456789');
//$passwordCrypt  este valor lo guardo al campo password de la BD





//Esto para el logeo del usuario
var_dump(crypt('123456789', $passwordCrypt));
var_dump($passwordCrypt);

if( crypt('123456789', $passwordCrypt) == $passwordCrypt) echo "OK";
else echo "FAIL";

?>


Resultado:
string(60) "$2y$07$omuYVZ2//iscACoKw6.pNemj7uOD4.NVDI9et/fl7MXPn3g66MHNi"

string(60)   "$2y$07$omuYVZ2//iscACoKw6.pNemj7uOD4.NVDI9et/fl7MXPn3g66MHNi"

OK


#!drvy

Hola,

Bueno al parecer, eso es una funcionalidad de crypt() para comparar hashes con diferentes algoritmos. Si te fijas en la pagina que te pase, http://php.net/manual/en/function.crypt.php

En el 1er ejemplo:
Código (php,4,5,6,7) [Seleccionar]
<?php
$hashed_password 
crypt('mypassword'); // let the salt be automatically generated

/* You should pass the entire results of crypt() as the salt for comparing a
   password, to avoid problems when different hashing algorithms are used. (As
   it says above, standard DES-based password hashing uses a 2-character salt,
   but MD5-based hashing uses 12.) */
if (crypt($user_input$hashed_password) == $hashed_password) {
   echo 
"Password verified!";
}
?>


Es decir, se usa para evitar problemas con diferentes algoritmos de hasheo. Por lo cual, se deduce que es un "extra" dentro del build.

Saludos