What is the correct format for a blowfish salt using PHP's crypt?
The number following the 2a
specifies the log2 of the number of rounds to perform. For example, 10 means do 1024 rounds. Usually, 10 is normal. Don't use numbers that are too big, or your password will take forever to verify.
See Why does BCrypt.net GenerateSalt(31) return straight away? for something related. :-)
Length of salt in CRYPT_BLOWFISH
This is due to how the salt is encoded. The actual salt is 128 bit but the encoded salt in the crypt
format is 22 character · 8 bit/character · 3/4 = 132 bit. So 4 bits of the encoded salt are not actually used.
This also means that there are 16 encoded salts that result in the same hash as the first four bits of their least significant character are identical:
$hashes = array();
$chars = array_merge(array('.','/'), range('A','Z'), range('a','z'), range('0','9'));
foreach ($chars as $char) {
$salt = 'QAZXSWEDCVFRTGBNHYUJM'.$char;
$hashes[$salt] = crypt('pass','$2a$08$'.$salt);
}
var_dump($hashes);
Here are the encoded salts that result in the same hash:QAZXSWEDCVFRTGBNHYUJM.
QAZXSWEDCVFRTGBNHYUJM/
QAZXSWEDCVFRTGBNHYUJMA
QAZXSWEDCVFRTGBNHYUJMB
QAZXSWEDCVFRTGBNHYUJMC
QAZXSWEDCVFRTGBNHYUJMD
QAZXSWEDCVFRTGBNHYUJME
QAZXSWEDCVFRTGBNHYUJMF
QAZXSWEDCVFRTGBNHYUJMG
QAZXSWEDCVFRTGBNHYUJMH
QAZXSWEDCVFRTGBNHYUJMI
QAZXSWEDCVFRTGBNHYUJMJ
QAZXSWEDCVFRTGBNHYUJMK
QAZXSWEDCVFRTGBNHYUJML
QAZXSWEDCVFRTGBNHYUJMM
QAZXSWEDCVFRTGBNHYUJMN
crypt
probably simply uses the first that encodes the internally used 128 bit salt, which is QAZXSWEDCVFRTGBNHYUJM.
. Blowfish salt length for the Crypt() function?
Blowfish salts should be 22 chars long (including the trailing $, so 21) - you can double check with var_dump(CRYPT_SALT_LENGTH)
, I can't verify this now but my guess is that less chars will return an error and more chars will be truncated.
Regarding your third question: yes, you should read and check the hash using the embedded salt (and cost) parameters from the hash itself.
different encryptions with crypt. what format should the salt be etc
The official documentation of the crypt
function has quite some information about the various modes, and what should be passed as their salt
parameter:
CRYPT_STD_DES
: two character salt from the alphabet./0-9A-Za-z
, i.e. an 12 bit salt.CRYPT_EXT_DES
: a_
character, then a 4 character iteration count, then a 4 character salt (each using the same alphabet).CRYPT_MD5
: a marker$1$
, then 9 more salt characters (using the same alphabet as above, I suppose).CRYPT_BLOWFISH
: a marker$2a$
, then a two digit cost parameter in the range 04 to 31 (meaning 24 to 231 iterations), then$
and a 22-digit salt (again, using the same alphabet as above).CRYPT_SHA256
: a marker$5$
, an optional round parameter indication ofrounds=
number$
(with a decimal number between 1000 and 999999999), and a 16-character salt (using the same alphabet as above).CRYPT_SHA512
: a marker$6$
, an optional round parameter indication ofrounds=
number$
(with a decimal number between 1000 and 999999999), and a 16-character salt (using the same alphabet as above).
How to automatically generate salt for crypt method with blowfish
A salt should be unique (for each password) and unpredictable. These two criterias are a bit difficult to fulfill with a deterministic computer, so the best thing you can do is, to use the random source of the operating system, to generate the salt.
Time stamps, as well as the mt_rand()
function, are not ideal, because one can argue that they are predictable. At least an attacker can narrow down (and therefore precalculate) the possible combinations for a certain period. While this may not have a big impact in practice, why not do the best you can?
Since PHP 5.3 you can safely use the mcrypt_create_iv()
function to read from the random source, then you will have to encode the binary string to the allowed alphabet. This is a possible implementation.
PHP 5.5 will have it's own functions password_hash()
and password_verify()
ready, to simplify this task. There is also a compatibility pack for PHP 5.3/5.4 available, downloadable at password_compat.
Am I using PHP's crypt() function correctly?
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
Related Topics
Laravel 5 Auth Post Submit - Tokenmismatchexception in Verifycsrftoken.PHP Line 46
How to Remove Backslash on JSON_Encode() Function
PHP MySQL Pagination with Random Ordering
PHP Gd: How to Get Imagedata as Binary String
Get the Text of the Selected Option Using PHP
Download the Contents of a Url in PHP Even If It Returns a 404
Howto Generate JSON with Smarty
How to Access Magento Customer's Session from Outside Magento
Apache Virtual Host Not Parsing PHP
How to Convert Ldap Timestamp to Unix Timestamp
Calling a Stored Procedure from Codeigniter's Active Record Class
Function to Add Dashes to Us Phone Number in PHP
Codeigniter $This->Input->Post() Empty While $_Post Is Working Correctly
How to Remove Email Addresses and Links from a String in PHP