I've been using PHP's crypt()
as a way to store and verify passwords in my database. I use hashing for other things, but crypt()
for passwords. The documentation isn't that good and there seems to be a lot of debate. I'm using blowfish and two salts to crypt a password and store it in the database. Before I would store the salt and the encrypted password, (like a salted hash) but realized its redundant because the salt is part of the encrypted password string.
I'm a little confused on how rainbow table attacks would work on crypt()
, anyway does this look correct from a security standpoint. I use a second salt to append to the password to increase the entropy of short passwords, probably overkill but why not?
function crypt_password($password) {
if ($password) {
//find the longest valid salt allowed by server
$max_salt = CRYPT_SALT_LENGTH;
//blowfish hashing with a salt as follows: "$2a$", a two digit cost parameter, "$", and 22 base 64
$blowfish = '$2a$10$';
//get the longest salt, could set to 22 crypt ignores extra data
$salt = get_salt ( $max_salt );
//get a second salt to strengthen password
$salt2 = get_salt ( 30 ); //set to whatever
//append salt2 data to the password, and crypt using salt, results in a 60 char output
$crypt_pass = crypt ( $password . $salt2, $blowfish . $salt );
//insert crypt pass along with salt2 into database.
$sql = "insert into database....";
return true;
}
}
function get_salt($length) {
$options = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./';
$salt = '';
for($i = 0; $i <= $length; $i ++) {
$options = str_shuffle ( $options );
$salt .= $options [rand ( 0, 63 )];
}
return $salt;
}
function verify_password($input_password)
{
if($input_password)
{
//get stored crypt pass,and salt2 from the database
$stored_password = 'somethingfromdatabase';
$stored_salt2 = 'somethingelsefromdatabase';
//compare the crypt of input+stored_salt2 to the stored crypt password
if (crypt($input_password . $stored_salt2, $stored_password) == $stored_password) {
//authenticated
return true;
}
else return false;
}
else return false;
}
Definition and Usage. The crypt() function returns a hashed string using DES, Blowfish, or MD5 algorithms. This function behaves different on different operating systems. PHP checks what algorithms are available and what algorithms to use when it is installed. The salt parameter is optional.
crypt() is the password encryption function. It is based on the Data Encryption Standard algorithm with variations intended (among other things) to discourage use of hardware implementations of a key search. key is a user's typed password. salt is a two-character string chosen from the set [a-zA-Z0-9./].
What is a salt? A cryptographic salt is data which is applied during the hashing process in order to eliminate the possibility of the output being looked up in a list of pre-calculated pairs of hashes and their input, known as a rainbow table.
You really should have a look at PHPASS: http://www.openwall.com/phpass/ It's a password hashing framework using crypt() which is used in projects like Wordpress and phpBB.
There is also an excellent article on this website about password hashing, salting and stretching using crypt(): http://www.openwall.com/articles/PHP-Users-Passwords
UPDATE: Currently there's an alternative for the PHPASS library. In the next version of PHP there are special functions for hashing and verifying passwords (using bcrypt): http://www.php.net/manual/en/ref.password.php. There is a compatibility library that implements these functions for PHP 5.3.7+: https://github.com/ircmaxell/password_compat
Your use of crypt()
is fine. crypt($input, $stored) == $stored
is the way it is designed to be used.
Your get_salt()
function is not great, since it is using the often-poor rand()
function. You should consider using a stronger random function, like openssl_random_pseudo_bytes()
, instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With