How to create and store password hashes with Blowfish in PHP
You should store the entire output of crypt, there's not a lot of point in splitting it up, because you need to generate a new salt for each password you're hashing in any case. Using a fixed hidden salt as mentioned by Matt is wrong - the salt should be different for every hash.
For more information see http://www.openwall.com/articles/PHP-Users-Passwords - I recommend using the phpass library because it handles generating a random salt for you, unlike crypt().
Related videos on Youtube
Admin
Updated on February 14, 2020Comments
-
Admin about 4 years
1) How do you create secure Blowfish hashes of passwords with crypt()?
$hash = crypt('somePassword', '$2a$07$nGYCCmhrzjrgdcxjH$');
1a) What is the significance of "$2a"? Does it just indicate that the Blowfish algorithm should be used?
1b) What is the significance of "$07"? Does a higher value imply a more secure hash?
1c) What is the significance of "$nGYCCmhrzjrgdcxjH$"? Is this the salt that will be used? Should this be randomly generated? Hard-coded?2) How do you store Blowfish hashes?
echo $hash; //Output: $2a$07$nGYCCmhrzjrgdcxjH$$$$.xLJMTJxaRa12DnhpAJmKQw.NXXZHgyq
2a) What part of this should be stored in the database?
2b) What data type should be used for the column (MySQL)?3) How should one verify a login attempt?
-
Linus Kleen about 13 years1.) Read the manual 2. & 3. are questions for themselves.
-
-
Matt about 13 yearsNote, the above shouldn't be used for a login to protect sensitive data. For that, as a minimum, use a different salt for each user and store the salt value in a separate database (accessible only by a different MySQL user) with a table mapping the username to the salt.
-
Admin about 13 yearsMy CRYPT_SALT_LENGTH is 123, so your substr() line returnes an empty string. What's up with that?
-
Admin about 13 yearsI've used
$hash = substr($hash, strlen($salt));
or$hash = str_replace($salt, '', $hash);
. (They return the same.) Seems to work. It seems the final blowfish hash is 20 letters long, so CHAR(20) might be a proper datatype? -
user3391801 about 13 yearsThe answer above is just plain wrong. In crypt(), you store the entire result of crypt() and feed it back into itself later for validation...
-
user3391801 about 13 yearschargen.matasano.com/chargen/2007/9/7/… is another excellent resource.
-
Xeoncross about 12 years@TML, is right - this answer is bad advice. The salt should be unique for each hash and is stored as a suffix to the hash by
crypt()
automatically. -
rjha94 almost 12 yearsHaving a "fixed" salt is bad idea. The whole purpose of salt is to add "random" bits to an otherwise guessable (e.g. 12345678) password. The chances of attack against stored passwords succeeding with a fixed salt is higher.
-
Neven Boyanov over 11 yearsWhat is the reason to use a random salt for every crypt() if you're going to store that salt in the database, as part of the encrypted password? If your database security is compromised and the intruder has access to that table and can read the "encrypted" password fields, then they have plain access to your "super-secret" and randomly generated salt. Although every-time-random salt may make your crypt() work differently every time, your security will not be increased.
-
Neven Boyanov over 11 yearsMy comment above is not entirely correct. Storing the salt along with the hash will protect you against rainbow-tables look up - because there will be different hashes for the same password, but it will not protect you against brute-force or password-dictionaries. Ex.: if I have access to all the salts and hashes I will be able to check who has a password 'test' or '1234', etc. - isn't that true?
-
Luke about 10 yearsRather than PHPass I'm more inclined to used the built in functions provided by PHP. I believe from what I have read, that PHP automatically generates a salt when using the
password_hash()
functionIf omitted, a random salt will be generated by password_hash() for each password hashed. This is the intended mode of operation.
uk1.php.net/password_hash -
xyphoid about 10 yearsYes, since this post was written, PHP added password_hash - that is a better option than phpass now.