How do you use bcrypt for hashing passwords in PHP? -
every , hear advice "use bcrypt storing passwords in php, bcrypt rules".
but bcrypt
? php doesn't offer such functions, wikipedia babbles file-encryption utility , web searches reveal few implementations of blowfish in different languages. blowfish available in php via mcrypt
, how storing passwords? blowfish general purpose cipher, works 2 ways. if encrypted, can decrypted. passwords need one-way hashing function.
what explanation?
bcrypt
hashing algorithm scalable hardware (via configurable number of rounds). slowness , multiple rounds ensures attacker must deploy massive funds , hardware able crack passwords. add per-password salts (bcrypt
requires salts) , can sure attack virtually unfeasible without either ludicrous amount of funds or hardware.
bcrypt
uses eksblowfish algorithm hash passwords. while encryption phase of eksblowfish , blowfish same, key schedule phase of eksblowfish ensures subsequent state depends on both salt , key (user password), , no state can precomputed without knowledge of both. because of key difference, bcrypt
one-way hashing algorithm. cannot retrieve plain text password without knowing salt, rounds and key (password). [source]
how use bcrypt:
using php >= 5.5-dev
password hashing functions have been built directly php >= 5.5. may use password_hash()
create bcrypt
hash of password:
<?php // usage 1: echo password_hash('rasmuslerdorf', password_default)."\n"; // $2y$10$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // example: // $2y$10$.vga1o9wmrjrwavxd98hnogsnpdczlqm3jq7kned1rvagv3fykk1a // usage 2: $options = [ 'cost' => 11 ]; echo password_hash('rasmuslerdorf', password_bcrypt, $options)."\n"; // $2y$11$6dp.v0no7yi3iski4qog6oqi5eio6jnjsqg7vdnb.jggisxnion4c
to verify user provided password against existing hash, may use password_verify()
such:
<?php // see password_hash() example see came from. $hash = '$2y$07$bcryptrequires22chrcte/vlqh0pijtjxl.0t1xka8pw9dmxtpoq'; if (password_verify('rasmuslerdorf', $hash)) { echo 'password valid!'; } else { echo 'invalid password.'; }
using php >= 5.3.7, < 5.5-dev (also redhat php >= 5.3.3)
there compatibility library on github created based on source code of above functions written in c, provides same functionality. once compatibility library installed, usage same above (minus shorthand array notation if still on 5.3.x branch).
using php < 5.3.7 (deprecated)
you can use crypt()
function generate bcrypt hashes of input strings. class can automatically generate salts , verify existing hashes against input. if using version of php higher or equal 5.3.7, highly recommended use built-in function or compat library. alternative provided historical purposes.
class bcrypt { private $rounds; public function __construct($rounds = 12) { if (crypt_blowfish != 1) { throw new exception("bcrypt not supported in 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 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(); } } ($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) { // following code php password hashing framework $itoa64 = './abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789'; $output = ''; $i = 0; { $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; } }
you can use code this:
$bcrypt = new bcrypt(15); $hash = $bcrypt->hash('password'); $isgood = $bcrypt->verify('password', $hash);
alternatively, may use portable php hashing framework.
Comments
Post a Comment