Итак, прямо на него.PHP password_verify() vs Python bcrypt.hashpw()
У меня есть [простой] PHP REST API, где я получаю хэшированный пароль с помощью ключа заголовка X-API-KEY. Это отлично работает при взаимодействии с другим PHP-скриптом, и фраза хешируется с помощью метода password_hash() PHP. Однако, когда я пытаюсь взаимодействовать с API через Python и библиотеку Requests, ключ отклоняется. Вот некоторые примеры:
PHP:
<?php
$usrid = '123456';
$dt = new DateTime();
$secret = "secret{$usrid}{$dt->format('Ymd')}";
$hashed = password_hash($secret, PASSWORD_BCRYPT);
echo $secret."\n";
echo $hashed."\n";
echo(phpversion());
?>
Python:
#!/usr/bin/python
import bcrypt, datetime, sys
usrid = '123456' # user id
t = datetime.datetime.now().strftime('%Y%m%d')
secret = "secret{usrid}{t}".format(usrid=usrid,t=t)
hashed = bcrypt.hashpw(secret, bcrypt.gensalt())
print secret
print hashed
print '%d.%d.%d' % (sys.version_info[:3])
Выходной сигнал каждого из них следующим образом:
PHP:
secret12345620161116
$2y$10$/WUBS2RkTlfcgPxvmqYRI.EkBD/CPgnpE9rYvOqweERgSwFeENUDO
5.6.24
Python:
secret12345620161116
$2b$11$9v/l6KglHiNgOybw1Y8jWeCFHiAfv.cguO1Qmc7Noe4azSluoBeHO
2.7.11
Теперь, очевидно, они разные , то есть точка, но когда вы передаете вывод Python функции PHP password_verify(), она возвращает False. Результат PHP отлично проверяется.
Должно быть, что-то мне не хватает здесь, но, для жизни меня, я не могу найти его. Я пробовал использовать разные варианты солей без успеха. Что мне не хватает? Являются ли эти два просто несовместимыми? Это кажется глупым, если это правда.
Благодарим вас за продвинутые, интеллектуальные народы в Интернете.
UPDATE
[Я обновил скрипты с помощью следующих 2-х линий для испытаний]
PHP: $hashed = password_hash($secret, PASSWORD_BCRYPT, ['cost'=>11]);
Python: hashed = bcrypt.hashpw(secret, bcrypt.gensalt(11))
И я использовал это [PHP] для проверки выше:
<?php
$secret = 'secret12345620161116';
$php = '$2y$11$rMqK7PhWtYd3E6yqqor0K.p2XEOJqbxJSrknLLWfhqZKsbYRa1YRa'; // output from php script
$python = '$2b$11$yWzCNB4dfIIVH2FLWWEQ/efSmN/KlVmLq.MGJ54plgedE1OSQgvPu'; // putput from python script
$php_needs_rehash = password_needs_rehash($php, PASSWORD_BCRYPT);
$python_needs_rehash = password_needs_rehash($python, PASSWORD_BCRYPT);
echo 'php_needs_rehash: '.$php_needs_rehash."\n";
echo 'python_needs_rehash: '.$python_needs_rehash."\n";
echo "\n";
echo "php_info:\n";
print_r(password_get_info($php));
echo "\n";
echo "python_info:\n";
print_r(password_get_info($python));
echo "\n";
echo "php_verified: ".password_verify($secret, $php)."\n";
echo "python_verified: ".password_verify($secret, $python)."\n";
echo "\n";
?>
Со следующим выходом:
php_needs_rehash: 1
python_needs_rehash: 1
php_info:
Array
(
[algo] => 1
[algoName] => bcrypt
[options] => Array
(
[cost] => 11
)
)
python_info:
Array
(
[algo] => 0
[algoName] => unknown
[options] => Array
(
)
)
php_verified: 1
python_verified: 1
Итак, теперь я действительно запутался, так как сервер все еще не распознает мой хэшированный ключ python, если я не заменю «$ 2b» на «$ 2y», как было предложено richardhsu в комментариях, что является.
Из любопытства, какие версии PHP и Python вы тестировали? –
Если вы выходите 'secret' в PHP и в Python перед хешированием, то они одинаковы? –
PHP использует '$ 2y $' как идентификатор алгоритма bcrypt.Очевидно, что python использует другой идентификатор. Кроме того, следующее значение - стоимость. Различные затраты означают различное количество циклов, которые повторяется хеш. Попробуйте изменить стоимость php на '11', как хэш-код python (может быть установлен как один из параметров password_hash) и посмотреть, совпадает ли он с хешем python минус алгоритм. –