I have password hashes stored in a Postgresql database generated with:
password_hash($password, PASSWORD_DEFAULT);
Now I would like to also be able to verify a user password with Postgresql and pgcrypto.
But pgcrypto's crypt()
function is not able to verify the existing password hashes.
However - I can verify password hashes generated by Postgresql with PHP's password_verify
.
For example:
password_hash('hello', PASSWORD_DEFAULT);
$2y$10$fD2cw7T6s4dPvk1SFHmiJeRRaegalE/Oa3zSD6.x5WncQJC9wtCAS
postgres=# SELECT crypt('hello', gen_salt('bf'));
crypt
--------------------------------------------------------------
$2a$06$7/AGAXFSTCMu9r.08oD.UulYR0/05q7lmuCTC68Adyu/aNJkzpoIW
Verification:
// php_verify with the Postgresql hash
php > var_dump(password_verify('hello', '$2a$06$7/AGAXFSTCMu9r.08oD.UulYR0/05q7lmuCTC68Adyu/aNJkzpoIW'));
bool(true)
postgres=# SELECT crypt('hello', '$2y$10$fD2cw7T6s4dPvk1SFHmiJeRRaegalE/Oa3zSD6.x5WncQJC9wtCAS');
crypt
---------------
$2JgKNLEdsV2E
(1 Zeile)
My questions are basically:
From the answer to: Where 2x prefix are used in BCrypt? which has all the gory details about the $2$ variants born from implementation bugs:
There is no difference between 2a, 2x, 2y, and 2b. If you wrote your implementation correctly, they all output the same result.
Based on that, one may take the hash generated by PHP's password_hash
, replace the leading $2y$
by $2a$
and pass it as the second argument of pgcrypto's crypt()
.
Using the value from your example:
postgres=# \set hash '$2a$10$fD2cw7T6s4dPvk1SFHmiJeRRaegalE/Oa3zSD6.x5WncQJC9wtCAS'
postgres=# SELECT crypt('hello', :'hash') = :'hash'
?column?
----------
t