2016-11-16 71 views
6

所以,對它。PHP password_verify()vs Python bcrypt.hashpw()

我已經設置了一個[簡單] PHP REST API,其中通過X-API-KEY標頭鍵接收哈希密碼。當與另一個PHP腳本接口並且通過PHP的password_hash()方法對短語進行哈希處理時,這非常有效。但是,當我嘗試通過Python和請求庫與API進行交互時,密鑰被拒絕。下面是一些樣本:

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

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

[I具有與以下兩行的測試更新腳本]我已經使用這個[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散列鍵,如果我沒有用richardhsu在評論中建議的「$ 2y」替換「$ 2b」是。

+0

出於好奇,您測試了哪些版本的PHP和Python? –

+1

如果你在散列之前用PHP和Python輸出'secret',它們是一樣的嗎? –

+2

PHP使用'$ 2y $'作爲「bcrypt」算法標識符。顯然python使用不同的標識符。另外,下一個值是成本。不同的成本意味着哈希將重複的循環次數不同。嘗試像python哈希(可以設置爲password_hash的選項之一)將php成本更改爲'11',並查看它是否與python哈希值減去算法一致。 –

回答

0

技術上它們都是不同版本bcrypt或隱窩河豚

在PHP前綴是$ 2Y $ 10 $ 在python前綴是$ 2B $ $ 11

這意味着成本因素是略微分別不同的10比11 在你更新你有固定的成本因素,都爲11

前綴的另一部分表示PHP是用Python的地方使用它是基於Blowfish加密bcrypt的散列crypt_blowfish的。

由於這些差異,2個密碼不可互換。

+1

BCrypt算法是基於河豚密碼,兩個平臺使用相同的算法BCrypt雖然。不同的成本因素不會使哈希值不相容,BCrypt的設計允許使用不同的成本因素進行驗證。 – martinstoeckli