2016-08-19 64 views
0

我們正在將認證模塊從PHP遷移到Java。目前使用BCrypt算法將密碼hash + salt存儲在數據庫中。該值是使用PHP的password_hash()函數生成的。爲驗證純文本密碼,我們使用PHP的password_verify()函數。無法驗證使用php password_hash()使用jBcrypt創建的passwordhash + salt

PHP代碼

$hash = password_hash($password,PASSWORD_DEFAULT); //stored in db 

if(password_verify($candidate,$hash)===TRUE) { //$hash fetched from DB 
    echo "valid"; 
} 

對於遷移此驗證模塊爲Java,我們使用jBCrypt庫通過使用jBCrypt-0.4.jar

Java代碼

private static String hashPassword(String password) { 
    String hashed = BCrypt.hashpw(password, BCrypt.gensalt()); 
    return hashed; 
} 

private static boolean checkpasword(String candidate, String hashed){ 
    boolean matches = false; 

    if (BCrypt.checkpw(candidate, hashed)){ 
     matches = true; 
    } 

    return matches; 
} 

然而,從產生的passwordhash +鹽在java中沒有驗證php。對於字符串 'ABCD',生成的哈希+鹽是

PHP - $2y$10$SA4iLMAniuNO6p9P1ZJElePaJvlN5eHGZ2dDt2Mutle4FQr1OY4hC

Java - $2a$10$YnqJT5NPCPTI8qKBbLfgIOIOW4eckdbE1R85tJGNRUJKmxz1TLkWG

當我試圖使用在Java中使用PHP生成的字符串匹配

if (BCrypt.checkpw("abcd", "$2y$10$SA4iLMAniuNO6p9P1ZJElePaJvlN5eHGZ2dDt2Mutle4FQr1OY4hC")){ 
    matches = true; 
}

我得到的低於

線程「main」中的異常java.lang.Illegal ArgumentException的:無效的鹽修訂 在org.mindrot.jbcrypt.BCrypt.hashpw(BCrypt.java:665) 在org.mindrot.jbcrypt.BCrypt.checkpw(BCrypt.java:764)...`

如何使兩者兼容?

回答

1

在PHP中由password_hash()生成的散列包含salt。這意味着當您使用純文本密碼進行檢查時,會使用相同的salt來針對明文密碼生成哈希,並將這兩個哈希以的恆定時間方式進行比較以進行驗證。

您在Java中所做的每次都會生成不同的鹽,這意味着您無法比較兩者。您的Java實現使用不同的版本,在您的散列中用$2a$表示。注意PHP使用的是$2y$,鹽類明顯不同。 5.3.7之前的PHP

From the PHP manual

版本只支持「$2a$」作爲前綴鹽:PHP 5.3.7引入的新的前綴來修復河豚實施安全漏洞。請參閱» this document瞭解安全修復程序的完整詳細信息,但總而言之,僅針對PHP 5.3.7及更高版本的開發人員應優先使用「$2y$」而不是「$2a$」。

因此,您不應該在Java中生成一個新的哈希來驗證由PHP生成並存儲在數據庫中的現有哈希。相反,請將存儲的散列提供給BCrypt.checkpasword進行驗證。

+1

我不驗證時創建新的散列。我正在使用數據庫中現有的散列並與用戶輸入的純文本進行比較。我用我正在使用的確切代碼編輯了這個問題。 –

+3

好的,對不起,在這個問題中,你包含的代碼看起來像是你正在調用'hashPassword'。無論如何,你的Java實現可能不會像'$ 2y $'標識符。嘗試用Java中的'$ 2a $'替換它,然後將它發送到'checkpw'並查看是否有效。這不應該破壞任何東西,但如果它可能看看這個https://github.com/codebazz/jbcrypt/ – Sherif