2016-11-16 8 views
6

Итак, прямо на него.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 в комментариях, что является.

+0

Из любопытства, какие версии PHP и Python вы тестировали? –

+1

Если вы выходите 'secret' в PHP и в Python перед хешированием, то они одинаковы? –

+2

PHP использует '$ 2y $' как идентификатор алгоритма bcrypt.Очевидно, что python использует другой идентификатор. Кроме того, следующее значение - стоимость. Различные затраты означают различное количество циклов, которые повторяется хеш. Попробуйте изменить стоимость php на '11', как хэш-код python (может быть установлен как один из параметров password_hash) и посмотреть, совпадает ли он с хешем python минус алгоритм. –

ответ

0

Технически они являются различными версиями Bcrypt или крипты-Blowfish

в PHP префикс $ 2y $ 10 $ в питоне префикс $ 2b $ 11 $

Это означает, что факторы затрат немного разные 10 против 11 соответственно в вашем обновлении были исправлены факторы затрат на оба 11

другая часть префикса указывает на PHP использует CRYPT_BLOWFISH хэширования, где питон использует Bcrypt, который основан на шифром Blowfish.

Из-за этих различий 2 пароля не являются взаимозаменяемыми.

+1

Алгоритм BCrypt основан на cypher blowfish, обе платформы используют тот же алгоритм BCrypt. Другой фактор затрат не делает хеши несовместимыми, дизайн BCrypt позволяет проверять с различными факторами затрат. – martinstoeckli