2016-11-16 40 views
6

Tak, właśnie do niego.PHP password_verify() vs Python bcrypt.hashpw()

Mam ustawione [proste] PHP REST API, gdzie otrzymuję hashowane hasło za pomocą klucza nagłówkowego X-API-KEY. Działa to świetnie, gdy współpracujesz z innym skryptem PHP, a fraza jest mieszana za pomocą metody password_hash(). Jednak gdy próbuję połączyć się z interfejsem API za pośrednictwem Pythona i biblioteki Requests, klucz jest odrzucany. Oto kilka próbek:

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]) 

Wyjście każdy z nich jest w następujący sposób:

PHP: 
    secret12345620161116 
    $2y$10$/WUBS2RkTlfcgPxvmqYRI.EkBD/CPgnpE9rYvOqweERgSwFeENUDO 
    5.6.24 

Python: 
    secret12345620161116 
    $2b$11$9v/l6KglHiNgOybw1Y8jWeCFHiAfv.cguO1Qmc7Noe4azSluoBeHO 
    2.7.11 

Teraz, oczywiście są one różne , to jest sedno, ale kiedy przekazujesz wyjście Pythona do funkcji PHP password_verify(), to zwraca False. Wynik PHP weryfikuje się dobrze.

Musi tu być coś, czego tu brakuje, ale nie mogę go znaleźć na całe życie. Próbowałem używać różnych opcji soli bez powodzenia. czego mi brakuje? Czy te dwa po prostu nie są kompatybilne? To wydaje się głupie, jeśli to prawda.

Dziękuję zaawansowanym, inteligentnym ludziom internetowym.

UPDATE

[I zostały zaktualizowane skrypty z następujących 2 linie do testów]

PHP: $hashed = password_hash($secret, PASSWORD_BCRYPT, ['cost'=>11]); 
Python: hashed = bcrypt.hashpw(secret, bcrypt.gensalt(11)) 

I Użyłem tego [php], aby zweryfikować powyższą:

<?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"; 
?> 

Z następującą wydajnością:

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 

Tak więc, teraz jestem bardzo zdezorientowany, ponieważ serwer nadal nie rozpoznaje mojego zakodowanego klucza pytona, jeśli nie zastąpię "2 dolców" za pomocą "2 dolców", jak zasugerował richardhsu w komentarzach, że jest.

+0

Z ciekawości, jakie wersje PHP i Python testowałeś? –

+1

Jeśli wypiszesz 'secret' w PHP i Pythonie przed haszowaniem, czy są one takie same? –

+2

PHP używa '$ 2y $' jako identyfikatora algorytmu "bcrypt".Podobno Python używa innego identyfikatora. Kolejną wartością jest koszt. Różne koszty oznaczają inną liczbę cykli, którą powtarza hasz. Spróbuj zmienić koszt php na '11', tak jak hash pytona (można ustawić jako jedną z opcji password_hash) i sprawdzić, czy pasuje do skrótu Pythona minus algorytm. –

Odpowiedz

0

Technicznie obie są różne wersje bcrypt lub krypty-Blowfish

w php prefiks jest 2y $ $ 10 $ w Pythonie prefiks jest 2b $ 11 $ $

Oznacza to, że czynniki kosztowe są nieco różne 10 vs 11 odpowiednio w swojej aktualizacji ustaliłeś czynniki kosztowe na 11

Druga część przedrostka wskazuje, że php używa skrótu CRYPT_BLOWFISH, w którym pyton używa bcrypt, który jest oparty na szyfrze Blowfish.

Z powodu tych różnic 2 hasła nie są zamienne.

+1

Algorytm BCrypt oparty jest na szyfrowaniu blowfish, obie platformy używają tego samego algorytmu BCrypt. Inny czynnik kosztowy nie sprawia, że ​​hasze są niekompatybilne, a projekt BCrypt umożliwia weryfikację za pomocą różnych czynników kosztowych. – martinstoeckli