4

我有一个邮件服务器,它使用以下 sql 将邮箱密码存储在 mysql 数据库中:

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

但是数据库中没有存储盐。

现在我需要围绕这个数据库构建一个登录过程,但由于缺少盐,很难比较存储的密码。我注意到,密码哈希以以下形式将盐保存在其中:

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

如何创建可比较的密码哈希来构建登录?

Dovecot 能够使用存储的密码登录用户,但如何?

4

1 回答 1

5

MySQLENCRYPT()函数调用crypt(3) Unix 库函数,它实现了多种密码散列算法。使用的具体算法由salt参数选择,该参数应以美元符号包围的算法标识符开头;例如,以 开头的盐$1$对应于Poul Henning-Kamp 的旧的基于 MD5 的散列方案

(选择算法的这种相当奇怪的方式的原因是历史;1976 年基于 DES 的原始 crypt(3) 设计不支持替代散列算法,因此指定它们的方法必须硬塞到现有接口中为了保持与旧密码数据库的兼容性。事实证明,生成的系统非常漂亮和灵活,即使乍一看有点奇怪。)

无论如何,所有 crypt(3) 散列算法(包括原始的基于 DES 的算法)总是在输出的开头包含盐(以及嵌入其中的算法标识符),并忽略附加到末尾的任何额外数据盐输入。因此,要验证密码哈希,您只需将原始哈希ENCRYPT()作为盐输入,并检查它是否等于输出:

SELECT user_id,
  password_hash = ENCRYPT('password', password_hash) AS password_is_correct
FROM user_table WHERE user_id = 12345;
于 2013-02-10T20:03:14.733 回答