不保存盐的加盐密码哈希

4

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

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

但是数据库中没有存储盐。现在我需要围绕这个数据库建立一个登录流程,但由于缺少盐,比较存储的密码很困难。我注意到,密码哈希本身以以下形式保存盐:

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

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

Dovecot能够使用存储的密码来登录用户,但是它是如何实现的呢?


1
ENCRYPT()不是哈希函数。你应该使用bcrypt、scrypt或PBKDFv2。 - SLaks
是的,那可能是正确的,我会去改变它。但首先我需要更深入地了解它,并理解它的实际运作方式。 - user2059250
2
@SLaks:实际上,是的。我同意这个函数名非常误导人。 - Ilmari Karonen
1个回答

5
MySQL ENCRYPT() 函数 调用了实现多种密码哈希算法的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;

很棒的答案。也许可以添加示例输出并突出盐部分? - Antti Rytsölä

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接