15 means strength and 15 is very slow.
Make sure you use this right or you'll get a severe performance penalty if you do verifications or hashing too often. Both operations take the same time to complete. Do a microtime()
on your exact scenario. 15 is not performance friendly.
I usually use 7 - 10. More is overkill...
PS: You'll find some lengthy posts here on SO
about bcrypt. Read them!
Like this: https://security.stackexchange.com/questions/4781/do-any-security-experts-recommend-bcrypt-for-password-storage or this http://michaelwright.me/php-password-storage
PPS: Local test:
15 strength takes around 3 seconds. Now imagine on a shared host :) You won't probably drop under 1 second. Which is too long IMO.
ACTUAL CODE:
// Is it available on this system?
$Availability = function_exists('crypt') and defined('CRYPT_BLOWFISH');
// And now the code:
$MT = microtime(true); // Time things, so we can get scared
$Password = 'somepassword'; // The password
$Salt = 'addsomevalidsalthere'; // Your salt, must be valid, read docs
$Strength = 15; // Strength (1-99)
// Compute the formatted salt required for crypt
$CryptSalt = sprintf('$2a$%02d$%s$', $Strength, $Salt);
// Hash the use $Password for storage
$Hashed = crypt($Password, $CryptSalt);
// Verify it against the user input $Password
$Verified = crypt($Password, $Hashed) === $Hashed;
// Show the duration of this (2x as it's both in and out)
echo number_format(microtime(true) - $MT, 6), PHP_EOL;
It's documented. Use for testing.
Just don't design your code to test the hash on each page load. That will kill your site's performance.
- Hash when creating a new user or changing the password.
- Verify when logging in an user.
- And in the rest, use some hashing mechanism that's fast to test on each logged-in page load.
You'll notice when you're doing it wrong. In your site's load speed :)
EXPLANATION:
When you hash with blowfish crypt, you need a salt, a strength and a password. You combine the salt and strength as the specs requires you to and you create a crypt()
compatible salt. This salt is translated by crypt()
and the sale and strength is extracted, plus the hashing algorithm based on character 2 and 3.
In your database, you store the final hash value. You don't store the salt you used to hash the password as you will defeat the purpose. The hashcrypted value stores what it needs to perform the reverse operation and check if your plain password matches the hashed one. The salt is stored within, no need for you to store it.
When the user is registered, you hash the password and save it. When they login, you verify the hashed password against the plain one they submit in your form. No need to remember the hash used to hash. And this allows you to generate random hashes on each hashing without caring what that value is as it's bundled in the returned hash. See more on the crypt() page on php.net.
Let me know if this made sense.