2013-02-10 108 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