Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Simple PHP 5.3+ Bcrypt functions
<?php
// ================================================================================================================
// Bcrypt hashing and hash checking wrapper functions for simplified, secure password encryption
// ================================================================================================================
// Create a bcrypt_hash.
function bcrypt_hash($password, $work_factor = 8)
{
if (version_compare(PHP_VERSION, '5.3') < 0) throw new Exception('Bcrypt requires PHP 5.3 or above');
if (! function_exists('openssl_random_pseudo_bytes')) {
throw new Exception('Bcrypt requires openssl PHP extension');
}
if ($work_factor < 4 || $work_factor > 31) $work_factor = 8;
$salt =
'$2a$' . str_pad($work_factor, 2, '0', STR_PAD_LEFT) . '$' .
substr(
strtr(base64_encode(openssl_random_pseudo_bytes(16)), '+', '.'),
0, 22
)
;
return crypt($password, $salt);
}
// Check a password against a bcrypt hash.
function bcrypt_check($password, $stored_hash, $legacy_handler = NULL)
{
if (version_compare(PHP_VERSION, '5.3') < 0) throw new Exception('Bcrypt requires PHP 5.3 or above');
if (bcrypt_is_legacy_hash($stored_hash)) {
if ($legacy_handler) return call_user_func($legacy_handler, $password, $stored_hash);
else throw new Exception('Unsupported hash format');
}
// Use the php-native function crypt to match the hashes.
return crypt($password, $stored_hash) == $stored_hash;
}
// Check whether the hash was created for bcrypt, or else for some other purpose.
function bcrypt_is_legacy_hash($hash) { return substr($hash, 0, 4) != '$2a$'; }
/* Sample usage:
By Marco Arment <me@marco.org>.
This code is released in the public domain.
THERE IS ABSOLUTELY NO WARRANTY.
Usage example:
// In a registration or password-change form:
$hash_for_user = Bcrypt::hash($_POST['password']);
// Hash the password.
// In a login form:
// Check the incoming password against the stored hash.
$is_correct = Bcrypt::check($_POST['password'], $stored_hash_for_user);
// For backwards-compatibility when some entries are hashed using a different method.
// In a login form when migrating entries gradually from a legacy SHA-1 hash:
$is_correct = Bcrypt::check(
$_POST['password'],
$stored_hash_for_user,
function($password, $hash) { return $hash == sha1($password); }
);
// This would change from the old hash to using a new hash based on bcrypt.
if ($is_correct && Bcrypt::is_legacy_hash($stored_hash_for_user)) {
$user->store_new_hash(Bcrypt::hash($_POST['password']));
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment