문제

I'm hashing my password with bcrypt (actually with password_compat since I run php 5.3.10)
I wanted to split the result string of the function into two parts: the salt used and the hash itself. (I know to use password_verify() to verify, well, the password. But I need the hash to use it as a key to encrypt a private key in a more broader security system.)

For a given password (abcdef) this is the result:

 $2y$10$ult68Ti4/zEWX4VQ       ....           YCOWjL6

I've altered the function a little bit, to spit out the concat, salt, hash and hash_format.

 ... from the password_compat ...
 $salt = substr($salt, 0, $required_salt_len);
 $hash = $hash_format . $salt;
 $ret = crypt($password, $hash);
 if (!is_string($ret) || strlen($ret) <= 13) {
        return false;
 }

 return array( 'concat'=>$ret, 
               'salt'=>$salt, 
               'format'=>$hash_format,
               'hash_format'=>$hash);

I thought the result-hash was a concat of the $hash_format, $salt and the hash... but the last character is different...

                                               _
[concat] =>        $2y$10$oWfFYcNqlcUeGwJM0AFUguSJ5t  .....  SvWG
[salt] =>                 oWfFYcNqlcUeGwJM0AFUgw
[hash_format] =>   $2y$10$oWfFYcNqlcUeGwJM0AFUgw
[format] =>        $2y$10$
                                               ^

As you can see the last character is different in the salt before the crypt function and after the function.

How is this possible?

도움이 되었습니까?

해결책

The reason why the salt passed to crypt() can differ from the salt returned in the resulting hash-value is, that BCrypt internally only uses 126 bits of the salt, but the salt passed to the function always contains 128 bits. Since the crypt function expects the salt kind of base64 encoded, you cannot pass 126 bits directly.

A more detailed answer you can find here: Why does crypt/blowfish generate the same hash with two different salts?

I understand that you want to use the real hash as a key to encrypt another key, you could extract it from the resulting hash-value. This string is always of a certain format with $ to separate the parts, with BCrypt the real hash are the last 31 characters

$2y$10$nOUIs5kJ7naTuTFkBy1veuK0kSxUFXfuaOKdOKf9xYT0KKIGSJwFa
 |  |  |                     |
 |  |  |                     hash-value = K0kSxUFXfuaOKdOKf9xYT0KKIGSJwFa
 |  |  |
 |  |  salt = nOUIs5kJ7naTuTFkBy1veu (22 characters)
 |  |
 |  cost-factor = 10 = 2^10 iterations
 |
 hash-algorithm = 2y = BCrypt

Another possibility is to calculate a hash of the whole string (all 60 characters). You could choose an algorithm that returns the required length, e.g. sha256 to get a 256 bit key for MCRYPT_TWOFISH.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top