2011-06-08 84 views
5

我正在使用Play 1.2.1。我想散列我的用戶密碼。我認爲Crypto.passwordHash會很好,但事實並非如此。 passwordHash文檔說它返回MD5密碼哈希值。我創建了一些固定的用戶帳戶,在這裏我把MD5哈希密碼:玩!哈希密碼返回錯誤結果

... 
User(admin): 
    login: admin 
    password: f1682b54de57d202ba947a0af26399fd 
    fullName: Administrator 
    ... 

的問題是,當我嘗試登錄,像這樣的東西:

user.password.equals(Crypto.passwordHash(password)) 

,它不工作。所以我把日誌語句在我autentify方法:

Logger.info("\nUser hashed password is %s " + 
        "\nPassed password is %s " + 
        "\nHashed passed password is %s", 
        user.password, password, Crypto.passwordHash(password)); 

,密碼哈希確實不同,但是,嘿! passwordHash方法的輸出甚至不是一個MD5哈希:

15:02:16,164 INFO ~ 
User hashed password is f1682b54de57d202ba947a0af26399fd 
Passed password is <you don't have to know this :P> 
Hashed passed password is 8WgrVN5X0gK6lHoK8mOZ/Q== 

怎麼樣?如何解決它?或者,也許我必須實施我自己的解決方案?

+0

順便說一句,使用簡單的MD5-Hash密碼並不是很聰明。另外至少應該有一種鹽。 – niels 2011-06-09 18:20:03

+0

@niels - 我知道,但這只是一個簡單的學習遊戲示例項目! – jjczopek 2011-06-09 18:22:07

+0

我想你可能會喜歡下面鏈接的答案,它建議如何在java http:// stackoverflow中使用md5。com/questions/415953/generate-md5-hash-in-java – engin 2011-06-08 13:43:11

回答

5

當您比較十六進制編碼時,Crypto.passwordHash返回base64編碼的密碼哈希。

+2

我個人認爲文檔應該提及這個細節。 – jjczopek 2011-06-08 14:35:40

2

由於Nickolay說你正在比較Hex與Base-64字符串。另外,我建議使用BCrypt,而不是Play的Crypto工具。

3

MD5輸出16個字節的序列,每個字節具有(可能)0至255(包括端點)之間的任何值。當您想要打印的值時,需要將字節轉換爲一系列「可打印字符」。有幾種可能的約定,兩個主要是十六進制Base64。以十六進制表示法,每個字節值表示爲兩個「十六進制數字」:這樣的數字是十進制數字('0'到'9')或字母(從'a'到'f',案件無關緊要)。這16個字節因此變成了32個字符。

在Base64編碼中,三個連續字節的每個組都被編碼爲四個字符,取自64個可能字符(數字,小寫字母,大寫字母,'+'和'/')的列表。可以添加一個或兩個最終的'='符號,以便編碼的字符串包含多個4的倍數的字符。

這裏,'8WgrVN5X0gK6lHoK8mOZ/Q =='是16的序列的Base64編碼字節,第一個值爲241,第二個爲104,然後爲43,依此類推。在十六進制表示法中,第一個字節由'f1'表示,第二個字節由'68'表示,第三個由'2b'...表示,而16字節完整序列的十六進制表示法則爲'f1682b54de57d202ba947a0af26399fd',值你的預期。

play.libs.Codec類包含解碼和編碼Base64和十六進制符號的方法。它還包含Codec.hexMD5(),它執行MD5散列並以十六進制符號而不是Base64返回值。