<?php $salt = '34a@$#aA9823$'; $password = 'dinvaders1234'; $password = hash('sha256', $salt . $password); ?>opta por cualquiera de estas dos opciones para generar datos aleatorios, primero considera usar mcrypt_create_iv que crea un vector de inicialización (IV) desde una fuente aleatoria, el primer parametro representa el tamaño del vector y el segundo parametro representa la fuente del IV. El parámetro fuente puede ser MCRYPT_RAND (generador de números aleatorios del sistema), MCRYPT_DEV_RANDOM (lee datos de /dev/random) y MCRYPT_DEV_URANDOM (lee datos de /dev/urandom). Antes de 5.3.0, MCRYPT_RAND era la única soportada en Windows. Obsérvese que el valor predeterminado de este parámetro era MCRYPT_DEV_RANDOM antes de PHP 5.6.0.
<?php // A Crypt no le gustan los '+' así que los vamos a reemplazar por puntos. $salt = strtr(base64_encode(mcrypt_create_iv(22, MCRYPT_DEV_URANDOM)), '+', '.'); ?>o bien esta segunda opcion que utiliza openssl_random_pseudo_bytes que genera una cadena de bytes pseudo-aleatoria, con el número para crear aleatoriamente 22 numeros:
<?php // Generamos un salt aleatorio, de 22 caracteres para Bcrypt $salt = substr(base64_encode(openssl_random_pseudo_bytes('30')), 0, 22); // A Crypt no le gustan los '+' así que los vamos a reemplazar por puntos. $salt = strtr($salt, array('+' => '.')); ?>crypt — Hash de cadenas de un sólo sentido(PHP 4, PHP 5) Vamos a lo importante, primero mostrare como utilizar la función crypt sobre una contraseña y como validarla, no ingresare la contraseña a la base de datos
<?php $username = 'Admin'; $password = 'pabletoreto'; // costo base 2 $cost = 10; // Creamos una salt aleatoria de 16 elementos $salt = strtr(base64_encode(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM)), '+', '.'); // $2a$ significa Blowfish algorithm y %02d$ es el costo // deben ir antes de la salt para ser un formato aceptado // por la funcion crypt $salt = sprintf("$2a$%02d$", $cost) . $salt; $hash = crypt($password, $salt); echo ""; echo ""; echo "se obtuvo este valor encryptado" .$hash; echo ""; echo ""; echo "Ahora probaremos la validacion con pabletoreto de contraseña"; echo ""; $password2="pabletoreto"; //Vamos a verificar if(password_verify($password2, $hash)){ echo "OK, validacion correcta"; } else { echo "validacion incorrecta"; } ?>Podríamos haber verificado la contraseña con if ( hash_equals($hash, crypt($password2, $hash))) pero debes verificar que tu versión de PHP lo permita. crypt() devolverá el hash de un string utilizando el algoritmo estándar basado en DES de Unix o algoritmos alternativos que puedan estar disponibles en el sistema. El parámetro salt es opcional. Sin embargo, crypt() crea una contraseña débil sin salt. PHP 5.6 o posterior emiten un error de nivel E_NOTICE sin él. Asegúrese de especificar una sal lo suficientemente fuerte para mayor seguridad. password_hash — Crea un nuevo hash de contraseña (PHP 5 >= 5.5.0) password_hash() utiliza un hash fuerte, genera una sal fuerte, y aplica los redondeos necesarios automáticamente. password_hash() es una envoltura simple de crypt() compatible con los hash de contraseñas existentes. Se aconseja el uso de password_hash(). Lo bueno de password_hash() es que la misma función nos crea una salt segura, esta será aleatoria y diferente para cada password, el coste por defecto es 10 el cual es suficiente, estos dos valores ya están presentes en el hash que password_hash entrega, además que si utilizamos PASSWORD_DEFAULT como segundo parámetro es como que estuviéramos utilizando el algoritmo de hash BCRYPT, pero si queremos utilizar el algoritmo recomendado CRYPT_BLOWFISH se debe especificar como segundo parametro PASSWORD_BCRYPT. password_hash() crea un nuevo hash de contraseña usando un algoritmo de hash fuerte de único sentido. password_hash() es compatible con crypt(). Por lo tanto, los hash de contraseñas creados con crypt() se pueden usar con password_hash(), significa que podemos utilizar password_verify() para ambos casos. Actualmente, se tiene soporte para los siguientes algoritmos: PASSWORD_DEFAULT - Usar el algoritmo bcrypt (predeterminado a partir de PHP 5.5.0). Observe que esta constante está diseñada para cambiar siempre que se añada un algoritmo nuevo y más fuerte a PHP. Por esta razión, la longitud del resultado de usar este identificador puede cambiar en el tiempo. Por lo tanto, se recomienda almacenar el resultado en una columna de una base de datos que pueda apliarse a más de 60 caracteres (255 caracteres sería una buena elección). PASSWORD_BCRYPT - Usar el algoritmo CRYPT_BLOWFISH para crear el hash. Producirá un hash estándar compatible con crypt() utilizando el identificador "$2y$". El resultado siempre será un string de 60 caracteres, o FALSE en caso de error. Opciones admitias: salt - para proporcionar manualmente una sal a usar cuando se realiza el hash de la contraseña. Observe que esto sobrescribirá y prevendrá que una sal sea generada automáticamente. Si se omite, se generará una sal aleatoria mediante password_hash() para cada contraseña con hash. Este es el modo de operación previsto. cost - que denota el coste del algoritmo que debería usarse. Se pueden encontrar ejemplo de estos valores en la página de crypt(). Si se omite, se usará el valor predeterminado 10. Este es un buen coste de referencia, pero se podría considerar aumentarlo dependiendo del hardware. Entonces utilicemos password_hash, en la pagina de PHP se muestra este ejemplo de password_hash()
<?php /** * Queremos realizar un hash a nuestra contraseña cuando el algoritmo DEFAULT actual. * Actualmente es BCRYPT, y producirá un resultado de 60 caracteres. * * A que tener en cuenta que DEFAULT puede cambiar con el tiempo, por lo que debería prepararse * para permitir que el almacenamento se amplíe a más de 60 caracteres (255 estaría bien) */ echo password_hash("rasmuslerdorf", PASSWORD_DEFAULT)."\n"; ?>Ejemplo de password_hash() estableciendo el coste manualmente
<?php /** * En este caso, queremos aumentar el coste predeterminado de BCRYPT a 12. * Observe que también cambiamos a BCRYPT, que tendrá siempre 60 caracteres. */ $opciones = [ 'cost' => 12, ]; echo password_hash("rasmuslerdorf", PASSWORD_BCRYPT, $opciones)."\n"; ?>Ejemplo más completo con mysqli, aquí la conexión a la base de datos se encuentra en conexión.php pero esa la haces tu solo la utilizo emplicitamente en este código, además se dan las opciones de ingresar un nuevo password y de verificar password existentes, fíjate en elos $_POST[‘registrar’] y $_POST[‘ingresar’] y para verificar la contraseña contra el hash generado se utiliza password_verify($password_a_verificar, $hash_generado))
<?php session_start(); ob_start(); require_once "conexion.php"; error_reporting(E_ALL); if((isset($_POST['ingresar'])) or (isset($_POST['registrar']))){ if(!($mysqli = conectarse())){ echo "Error al conectarse a la base de datos"; echo ""; echo $mysqli->connect_errno. " - " .$mysqli->connect_error; exit(); } $errores = array(); $username = filter_var($username, FILTER_SANITIZE_STRING); $password = filter_var($password, FILTER_SANITIZE_STRING); if( empty($username) ) $errores[] = "Debe especificar username"; if( empty($password) ) $errores[] = "Debe especificar password"; if( count($errores) > 0 ) { echo "El algoritmo, coste y sal usados son devueltos como parte del hash. Por lo tanto, toda la información que es necesaria para verificar el hash, está incluida en él. Esto permite que la función password_verify() verifique el hash sin tener que almacenar por separado la información de la sal o del algoritmo. Uso alternativoERRORES ENCONTRADOS:
"; for( $contador=0; $contador < count($errores); $contador++ ) echo $errores[$contador]."
"; exit(); } if(isset($_POST['ingresar'])) { if(!($stmt = $mysqli->prepare("SELECT username, password FROM login_php WHERE username = ?"))){ echo "Prepare failed: (" . $mysqli->errno . ")" . $mysqli->error; exit(); } if(!$stmt->bind_param('s', $username)){ echo "Bind failed: (" . $stmt->errno . ")" . $stmt->error; exit(); } if(!$stmt->execute()){ echo "Execute failed: (" . $stmt->errno .")" . $stmt->error; exit(); } $userdata = $stmt->get_result(); $row = $userdata->fetch_array(MYSQLI_ASSOC); $stmt->store_result(); if(password_verify($password, $row['password'])){ $_SESSION['user'] = $username; header('Location: formulario.html'); exit(); }else{ echo "Login Failed: (" . $stmt->errno .")" . $stmt->error; exit(); } } if (isset($_POST['registrar'])){ $password_hash = password_hash($password, PASSWORD_DEFAULT); if(!($stmt = $mysqli->prepare("INSERT INTO login_php (username, password) VALUES (?,?)"))){ echo "Prepare failed: (" . $mysqli->errno . ")" . $mysqli->error; } if(!$stmt->bind_param('ss', $username, $password_hash)){ echo "Binding paramaters failed:(" . $stmt->errno . ")" . $stmt->error; } if(!$stmt->execute()){ echo "Execute failed: (" . $stmt->errno .")" . $stmt->error; } if($stmt) { header('Location: form_login.html'); } else{ echo "Registration failed"; } } }else{ header('location:form_login.html'); } $contenido = ob_get_contents(); ob_end_clean(); $stmt->close(); $mysqli->close(); ?>
<?php /** * Observe que la sal se genera aleatoriamente aquí. * No use nunca una sal estática o una que no se genere aleatoriamente. * * Para la GRAN mayoría de los casos de uso, dejar que password_hash genere la sal aleatoriamente */ $opciones = [ 'cost' => 11, 'salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM), ]; echo password_hash("rasmuslerdorf", PASSWORD_BCRYPT, $opciones)."\n"; ?>Ejemplo de password_hash() buscando un buen coste
<?php /** * Este código evaluará el servidor para determinar el coste permitido. * Se establecerá el mayor coste posible sin disminuir demasiando la velocidad * del servidor. 8-10 es una buena referencia, y más es bueno si los servidores * son suficientemente rápidos. El código que sigue tiene como objetivo un tramo de * ≤ 50 milisegundos, que es una buena referencia para sistemas con registros interactivos. */ $timeTarget = 0.05; // 50 milisegundos $coste = 8; do { $coste++; $inicio = microtime(true); password_hash("test", PASSWORD_BCRYPT, ["cost" => $coste]); $fin = microtime(true); } while (($fin - $inicio) < $timeTarget); echo "Coste conveniente encontrado: " . $coste . "\n"; ?>