0

From my understanding crypt(string, salt), takes the salt, tacks it onto the front of the encrypted version of the string parameter.

$pw = "secret";
$format_and_salt = $2y$10$MWRmZTkwMTc5ZGJjZDI1NT;
$hash = crypt($pw, $format_and_salt);

$hash gets stored to the database column hashed_password as $2y$10$MWRmZTkwMTc5ZGJjZDI1NOfGsQUgIu7ezETpe.uHjGqbmdrw2.vqm

or broken down:

first part is $format_and_salt: $2y$10$MWRmZTkwMTc5ZGJjZDI1N (sans the 'T')

+

second part is the encrypted $pw: OfGsQUgIu7ezETpe.uHjGqbmdrw2.vqm

If I then use crypt again to validate a password that a user submits to $_POST against the stored hashed_password in the database, the output for both cases doesn't seem to reflect the logic I described above. So I'm missing something.

So then:

$existing_hash = $admin['hashed_password'] ($admin being an array ultimately derived from a query).

and

crypt($pw, $existing_hash) returns $2y$10$MWRmZTkwMTc5ZGJjZDI1NOfGsQUgIu7ezETpe.uHjGqbmdrw2.vqm

which is identical to $hash above. This works to validate or invalidate the users submission to $_POST, but as mentioned, if I follow the logic for the first crypt() above, I would expect:

first part is $existing_hash: $2y$10$MWRmZTkwMTc5ZGJjZDI1NOfGsQUgIu7ezETpe.uHjGqbmdrw2.vqm

+

second part is the encrypted $pw: OfGsQUgIu7ezETpe.uHjGqbmdrw2.vqm

which I'd expect to combine as: $2y$10$MWRmZTkwMTc5ZGJjZDI1NOfGsQUgIu7ezETpe.uHjGqbmdrw2.vqmOfGsQUgIu7ezETpe.uHjGqbmdrw2.vqm

Can someone explain why the original crypt and the crypt just above that was used to validate the first one both have the same output? Thanks in advance.

dbconfession
  • 1,147
  • 2
  • 23
  • 36

1 Answers1

2

You're using Blowfish encryption - only the first 22 characters of the salt are used. This is one of the benefits of using blowfish.

From the PHP manual:

Blowfish hashing with a salt as follows: "$2a$", "$2x$" or "$2y$", a two digit cost parameter, "$", and 22 characters from the alphabet "./0-9A-Za-z".

This means that the salt from $existing_hash ends up being $2y$10$MWRmZTkwMTc5ZGJjZDI1N - exactly the same as previously.

mwotton
  • 2,170
  • 18
  • 36
  • Actually it's BCrypt hashing (Blowfish encryption is another thing), otherwise that's the correct answer. The crypt function only extracts the salt from the existing hash, and uses it to generate a comparable hash with the entered password. – martinstoeckli Dec 02 '14 at 14:09
  • `MWRmZTkwMTc5ZGJjZDI1N` is only 21 characters. Does the `$2y$10$` count as the 22nd character? – dbconfession Dec 02 '14 at 19:28
  • @martinstoeckli in the PHP implementation it's referred to as blowfish. Perhaps I should have said 'You're using the blowfish option'. – mwotton Dec 02 '14 at 20:59
  • @mwotton - Ah well, Blowfish is an encryption algorithm (two-way), while BCrypt is derrived from Blowfish but is a hash algorithm (one-way). It is indeed a bit confusing. – martinstoeckli Dec 02 '14 at 21:34
  • @dbconfession I wondered about that too - perhaps the `$` is being counted even though the manual indicates it should be 22 characters AFTER the `$` symbol. – mwotton Dec 02 '14 at 22:03
  • 1
    @dbconfession - BCrypt expects a salt of 22 characters, but it uses only 126 of the 128 bits. Thus your salt `MWRmZTkwMTc5ZGJjZDI1NT` can become `MWRmZTkwMTc5ZGJjZDI1NO`. See this [answer](http://stackoverflow.com/a/20927202/575765) for more details. – martinstoeckli Dec 03 '14 at 07:59