password_hash password_bcrypt password online encriptada ejemplo desencriptar contraseña con php passwords cryptography password-protection bcrypt

password_bcrypt - ¿Cómo se usa bcrypt para las contraseñas de hash en PHP?



password_hash online (9)

Edit: 2013.01.15 - Si su servidor lo admite, use la solución de martinstoeckli en su lugar.

Todo el mundo quiere hacer esto más complicado de lo que es. La función crypt () hace la mayor parte del trabajo.

function blowfishCrypt($password,$cost) { $chars=''./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789''; $salt=sprintf(''$2y$%02d$'',$cost); //For PHP < PHP 5.3.7 use this instead // $salt=sprintf(''$2a$%02d$'',$cost); //Create a 22 character salt -edit- 2013.01.15 - replaced rand with mt_rand mt_srand(); for($i=0;$i<22;$i++) $salt.=$chars[mt_rand(0,63)]; return crypt($password,$salt); }

Ejemplo:

$hash=blowfishCrypt(''password'',10); //This creates the hash $hash=blowfishCrypt(''password'',12); //This creates a more secure hash if(crypt(''password'',$hash)==$hash){ /*ok*/ } //This checks a password

Sé que debería ser obvio, pero por favor no use "contraseña" como su contraseña.

De vez en cuando escucho el consejo "Usar bcrypt para almacenar contraseñas en PHP, reglas de bcrypt".

Pero ¿qué es bcrypt ? PHP no ofrece ninguna de estas funciones, Wikipedia balbucea sobre una utilidad de cifrado de archivos y las búsquedas en la Web solo revelan algunas implementaciones de Blowfish en diferentes idiomas. Ahora Blowfish también está disponible en PHP a través de mcrypt , pero ¿cómo ayuda eso con el almacenamiento de contraseñas? Blowfish es un cifrado de propósito general, funciona de dos maneras. Si pudiera estar encriptado, podría ser descifrado. Las contraseñas necesitan una función de hashing unidireccional.

¿Cuál es la explicación?


Entonces, ¿quieres usar bcrypt? ¡Increíble! Sin embargo, al igual que otras áreas de la criptografía, no debería hacerlo usted mismo. Si necesita preocuparse por algo como administrar claves, almacenar sales o generar números aleatorios, lo está haciendo mal.

La razón es simple: es trivialmente fácil arruinar bcrypt . De hecho, si observa casi todos los códigos de esta página, notará que está violando al menos uno de estos problemas comunes.

Enfréntalo, la criptografía es dura.

Dejarlo para los expertos. Déjelo a las personas cuyo trabajo es mantener estas bibliotecas. Si necesitas tomar una decisión, lo estás haciendo mal.

En su lugar, simplemente use una biblioteca. Varios existen en función de sus necesidades.

Bibliotecas

Aquí hay un desglose de algunas de las API más comunes.

API PHP 5.5 - (Disponible para 5.3.7+)

A partir de PHP 5.5, se está introduciendo una nueva API para las contraseñas de hash. También hay una biblioteca de compatibilidad de shim mantenida (por mí) para 5.3.7+. Esto tiene la ventaja de ser una implementación revisada por pares y fácil de usar.

function register($username, $password) { $hash = password_hash($password, PASSWORD_BCRYPT); save($username, $hash); } function login($username, $password) { $hash = loadHashByUsername($username); if (password_verify($password, $hash)) { //login } else { // failure } }

Realmente, pretende ser extremadamente simple.

Recursos:

Zend / Crypt / Password / Bcrypt (5.3.2+)

Esta es otra API que es similar a la de PHP 5.5 y tiene un propósito similar.

function register($username, $password) { $bcrypt = new Zend/Crypt/Password/Bcrypt(); $hash = $bcrypt->create($password); save($user, $hash); } function login($username, $password) { $hash = loadHashByUsername($username); $bcrypt = new Zend/Crypt/Password/Bcrypt(); if ($bcrypt->verify($password, $hash)) { //login } else { // failure } }

Recursos:

PasswordLib

Este es un enfoque ligeramente diferente para el hashing de contraseñas. En lugar de simplemente admitir bcrypt, PasswordLib admite una gran cantidad de algoritmos de hash. Es principalmente útil en contextos en los que necesita compatibilidad con sistemas heredados y dispares que pueden estar fuera de su control. Es compatible con una gran cantidad de algoritmos de hash. Y es compatible con 5.3.2+

function register($username, $password) { $lib = new PasswordLib/PasswordLib(); $hash = $lib->createPasswordHash($password, ''$2y$'', array(''cost'' => 12)); save($user, $hash); } function login($username, $password) { $hash = loadHashByUsername($username); $lib = new PasswordLib/PasswordLib(); if ($lib->verifyPasswordHash($password, $hash)) { //login } else { // failure } }

Referencias:

  • Código fuente / documentación: GitHub

PHPASS

Esta es una capa que admite bcrypt, pero también es compatible con un algoritmo bastante fuerte que es útil si no tiene acceso a PHP> = 5.3.2 ... En realidad, es compatible con PHP 3.0+ (aunque no con bcrypt).

function register($username, $password) { $phpass = new PasswordHash(12, false); $hash = $phpass->HashPassword($password); save($user, $hash); } function login($username, $password) { $hash = loadHashByUsername($username); $phpass = new PasswordHash(12, false); if ($phpass->CheckPassword($password, $hash)) { //login } else { // failure } }

Recursos

Nota: ¡No use las alternativas de PHPASS que no están alojadas en openwall, son proyectos diferentes!

Acerca de BCrypt

Si se da cuenta, cada una de estas bibliotecas devuelve una sola cadena. Eso es por cómo funciona internamente BCrypt. Y hay un montón de respuestas sobre eso. Aquí hay una selección que he escrito, que no copiaré / pegaré aquí, pero enlazaré a:

Envolver

Hay muchas opciones diferentes. Lo que elijas depende de ti. Sin embargo, le recomendaría ALTAMENTE que use una de las bibliotecas anteriores para manejar esto por usted.

Nuevamente, si está usando crypt() directamente, probablemente esté haciendo algo mal. Si su código usa hash() (o md5() o sha1() ) directamente, definitivamente está haciendo algo mal.

Solo usa una biblioteca ...


La versión 5.5 de PHP tendrá soporte incorporado para BCrypt, las funciones password_hash() y password_verify() . En realidad, estos son solo envoltorios alrededor de la función crypt() , y harán que sea más fácil de usar correctamente. Se encarga de la generación de una sal aleatoria segura y proporciona buenos valores predeterminados.

La forma más fácil de usar estas funciones será:

$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT); $isPasswordCorrect = password_verify($password, $existingHashFromDb);

Este código codificará la contraseña con BCrypt (algoritmo 2y ), generará un salt aleatorio de la fuente aleatoria del sistema operativo y usará el parámetro de costo predeterminado (en este momento es 10). La segunda línea verifica si la contraseña ingresada por el usuario coincide con un valor hash ya almacenado.

Si desea cambiar el parámetro de costo, puede hacerlo de esta manera, aumentando el parámetro de costo en 1, duplica el tiempo necesario para calcular el valor de hash:

$hash = password_hash($password, PASSWORD_BCRYPT, array("cost" => 11));

A diferencia del parámetro "cost" , es mejor omitir el parámetro "salt" , porque la función ya hace todo lo posible para crear una sal criptográficamente segura.

Para la versión 5.3.7 y posterior de PHP, existe un paquete de compatibilidad , del mismo autor que realizó la función password_hash() . Para versiones de PHP anteriores a 5.3.7 no hay soporte para crypt() con 2y , el algoritmo BCrypt seguro de Unicode. Uno podría reemplazarlo con 2a , que es la mejor alternativa para versiones anteriores de PHP.


Obtendrá mucha información en Suficiente con The Rainbow Tables: lo que necesita saber sobre esquemas de contraseña segura o el marco de hashing de contraseña de PHP portátil .

El objetivo es marcar la contraseña con algo lento, por lo que alguien que obtenga su base de datos de contraseñas morirá al intentar forzar la fuerza bruta (un retraso de 10 ms para verificar una contraseña no es nada para usted, mucho para alguien que intenta forzarla). Bcrypt es lento y se puede usar con un parámetro para elegir qué tan lento es.


Para las contraseñas de OAuth 2 :

$bcrypt = new /Zend/Crypt/Password/Bcrypt; $bcrypt->create("youpasswordhere", 10)


Pensamiento actual: los hashes deben ser los más lentos disponibles, no los más rápidos posibles. Esto suprime los ataques de mesa del arco iris .

También relacionado, pero con precaución: un atacante nunca debe tener acceso ilimitado a su pantalla de inicio de sesión. Para evitarlo: configure una tabla de seguimiento de direcciones IP que registre cada resultado junto con el URI. Si más de 5 intentos de inicio de sesión provienen de la misma dirección IP en un período de cinco minutos, bloquee con una explicación. Un enfoque secundario es tener un esquema de contraseña de dos niveles, como hacen los bancos. Poner un bloqueo por fallas en el segundo paso aumenta la seguridad.

Resumen: ralentice al atacante usando funciones hash que consumen mucho tiempo. Además, bloquee demasiados accesos a su inicio de sesión y agregue un segundo nivel de contraseña.


Puede crear un hash unidireccional con bcrypt utilizando la función crypt() PHP y pasando una sal Blowfish apropiada. Lo más importante de toda la ecuación es que A) el algoritmo no se ha comprometido y B) se le agrega correctamente cada contraseña . No use una sal para toda la aplicación; que abre toda la aplicación para atacar desde un único conjunto de tablas Rainbow.

PHP - Función de cripta


Una alternativa es usar scrypt, específicamente diseñado para ser superior a bcrypt por Colin Percival en su artículo . Hay una extensión de PHP scrypt en PECL . Idealmente, este algoritmo se incluiría en PHP para que se pueda especificar para las funciones password_ * (idealmente como "PASSWORD_SCRYPT"), pero aún no está disponible.


bcrypt es un algoritmo de hash escalable con hardware (a través de un número configurable de rondas). Su lentitud y múltiples rondas aseguran que un atacante debe implementar fondos y hardware masivos para poder descifrar sus contraseñas. Agregue a eso las salts por contraseña ( bcrypt REQUIERE a sales) y puede estar seguro de que un ataque es prácticamente inviable sin una cantidad ridícula de fondos o hardware.

bcrypt utiliza el algoritmo Eksblowfish para codificar contraseñas. Si bien la fase de cifrado de Eksblowfish y Blowfish es exactamente la misma, la fase de programación clave de Eksblowfish garantiza que cualquier estado posterior depende tanto de la sal como de la clave (contraseña del usuario), y ningún estado puede precomputarse sin el conocimiento de ambos. Debido a esta diferencia clave, bcrypt es un algoritmo de hashing de una sola vía. No puede recuperar la contraseña de texto sin formato sin conocer la sal, rondas y clave (contraseña). [ Source ]

Cómo utilizar bcrypt:

Usando PHP> = 5.5-DEV

Las funciones de hash de contraseña ahora se han incorporado directamente en PHP> = 5.5 . Ahora puede usar password_hash() para crear un hash bcrypt de cualquier contraseña:

<?php // Usage 1: echo password_hash(''rasmuslerdorf'', PASSWORD_DEFAULT)."/n"; // $2y$10$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // For example: // $2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a // Usage 2: $options = [ ''cost'' => 11 ]; echo password_hash(''rasmuslerdorf'', PASSWORD_BCRYPT, $options)."/n"; // $2y$11$6DP.V0nO7YI3iSki4qog6OQI5eiO6Jnjsqg7vdnb.JgGIsxniOn4C

Para verificar una contraseña proporcionada por un usuario contra un hash existente, puede usar password_verify() como tal:

<?php // See the password_hash() example to see where this came from. $hash = ''$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq''; if (password_verify(''rasmuslerdorf'', $hash)) { echo ''Password is valid!''; } else { echo ''Invalid password.''; }

Usando PHP> = 5.3.7, <5.5-DEV (también RedHat PHP> = 5.3.3)

Existe una biblioteca de compatibilidad en GitHub creada en base al código fuente de las funciones anteriores originalmente escritas en C, que proporciona la misma funcionalidad. Una vez que se instala la biblioteca de compatibilidad, el uso es el mismo que el anterior (menos la notación de matriz abreviada si aún se encuentra en la rama 5.3.x).

Utilizando PHP <5.3.7 (DEPRECATED)

Puede usar la función crypt() para generar hashes bcrypt de cadenas de entrada. Esta clase puede generar sales automáticamente y verificar hashes existentes contra una entrada. Si está utilizando una versión de PHP superior o igual a 5.3.7, se recomienda encarecidamente que utilice la función incorporada o la biblioteca de compatibilidad . Esta alternativa se proporciona sólo para fines históricos.

class Bcrypt{ private $rounds; public function __construct($rounds = 12) { if (CRYPT_BLOWFISH != 1) { throw new Exception("bcrypt not supported in this installation. See http://php.net/crypt"); } $this->rounds = $rounds; } public function hash($input){ $hash = crypt($input, $this->getSalt()); if (strlen($hash) > 13) return $hash; return false; } public function verify($input, $existingHash){ $hash = crypt($input, $existingHash); return $hash === $existingHash; } private function getSalt(){ $salt = sprintf(''$2a$%02d$'', $this->rounds); $bytes = $this->getRandomBytes(16); $salt .= $this->encodeBytes($bytes); return $salt; } private $randomState; private function getRandomBytes($count){ $bytes = ''''; if (function_exists(''openssl_random_pseudo_bytes'') && (strtoupper(substr(PHP_OS, 0, 3)) !== ''WIN'')) { // OpenSSL is slow on Windows $bytes = openssl_random_pseudo_bytes($count); } if ($bytes === '''' && is_readable(''/dev/urandom'') && ($hRand = @fopen(''/dev/urandom'', ''rb'')) !== FALSE) { $bytes = fread($hRand, $count); fclose($hRand); } if (strlen($bytes) < $count) { $bytes = ''''; if ($this->randomState === null) { $this->randomState = microtime(); if (function_exists(''getmypid'')) { $this->randomState .= getmypid(); } } for ($i = 0; $i < $count; $i += 16) { $this->randomState = md5(microtime() . $this->randomState); if (PHP_VERSION >= ''5'') { $bytes .= md5($this->randomState, true); } else { $bytes .= pack(''H*'', md5($this->randomState)); } } $bytes = substr($bytes, 0, $count); } return $bytes; } private function encodeBytes($input){ // The following is code from the PHP Password Hashing Framework $itoa64 = ''./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789''; $output = ''''; $i = 0; do { $c1 = ord($input[$i++]); $output .= $itoa64[$c1 >> 2]; $c1 = ($c1 & 0x03) << 4; if ($i >= 16) { $output .= $itoa64[$c1]; break; } $c2 = ord($input[$i++]); $c1 |= $c2 >> 4; $output .= $itoa64[$c1]; $c1 = ($c2 & 0x0f) << 2; $c2 = ord($input[$i++]); $c1 |= $c2 >> 6; $output .= $itoa64[$c1]; $output .= $itoa64[$c2 & 0x3f]; } while (true); return $output; } }

Puedes usar este código así:

$bcrypt = new Bcrypt(15); $hash = $bcrypt->hash(''password''); $isGood = $bcrypt->verify(''password'', $hash);

Como alternativa, también puede utilizar el Marco de hash PHP portátil .