2013-02-10 184 views
4

我有存儲郵箱的密碼在MySQL數據庫用下面的SQL一個郵件服務器:鹽漬密碼哈希不保存鹽

ENCRYPT([PASSWORT], concat(_utf8"$1$", right(md5(rand()), 8), _utf8"$")) 

但沒有存儲在數據庫中的鹽。

現在我需要圍繞這個數據庫建立一個登錄過程,但是很難比較存儲的密碼,因爲缺少鹽。我注意到,該密碼哈希持有以下形式在它自身的鹽:

$1$[SALT]$[PASSWORD-HASH] 

如何創建一個可比的密碼哈希來構建一個登錄?

Dovecot能夠使用存儲的密碼登錄用戶,但是如何?

+1

'ENCRYPT()'是不是哈希。您應該使用bcrypt或scrypt或PBKDFv2。 – SLaks 2013-02-10 18:18:01

+0

是的,那可能是對的,我將改變它。但首先我需要深入瞭解它,並瞭解它是如何工作的。 – user2059250 2013-02-10 18:25:52

+2

@SLaks:實際上,[它是](http://dev.mysql.com/doc/refman/5.6/en/encryption-functions.html#function_encrypt)。我同意這個名字是可怕的誤導。 – 2013-02-10 20:05:29

回答

5

MySQL ENCRYPT() function調用crypt(3) Unix library function,它實現了各種密碼散列算法。要使用的特定算法由salt參數選擇,該參數應以包含美元符號的算法標識符開頭;例如,以$1$開頭的鹽對應於old MD5-based hashing scheme by Poul Henning-Kamp。 (選擇算法的這種相當好奇的方式的原因是歷史的;原來基於DES的基於1976的crypt(3)設計不支持可選的哈希算法,所以用於指定它們的方法必須被鎖定到現有的接口爲了保持與舊密碼數據庫的兼容性,事實證明,由此產生的系統是相當不錯的和靈活的,即使它乍看起來有點奇怪。)

無論如何,所有crypt(3 )散列算法(包括original DES-based one)始終在輸出開始處包含salt(以及嵌入其中的算法標識符),並忽略附加到salt輸入末尾的任何額外數據。因此,以驗證密碼哈希,只需養活原來散到ENCRYPT()的鹽,並檢查它是否等於輸出:

SELECT user_id, 
    password_hash = ENCRYPT('password', password_hash) AS password_is_correct 
FROM user_table WHERE user_id = 12345; 
+0

很好的回答。也許增加示例輸出並突出顯示salt部分? – anttir 2013-02-11 07:46:14