如何在 JAVA 中为 Dovecot 使用 SHA512-CRYPT?

how to SHA512-CRYPT for Dovecot in JAVA?

我有一个带 MySQL 数据库的 Dovecot 服务器,用于存储用户名和密码。数据库中的密码采用 SHA512-CRYPT 方案。

我正在使用脚本将哈希密码插入数据库。

doveadm pw -s SHA512-CRYPT -p password -r 500000

我想使用 JAVA 应用程序散列密码。我找到 this questions 并尝试使用相同的密码 firstpassword 和盐 FooBarBaz 创建相同的结果哈希。出于某种原因,我得到的结果哈希是不同的,尽管我使用相同的哈希算法、salt 和密码。

这是我的 Java 代码:

byte[] password = "firstpassword".getBytes();
byte[] salt = "FooBarBaz".getBytes();

MessageDigest digest = MessageDigest.getInstance("SHA-512");
digest.reset();
digest.update(salt);
byte[] hashed = digest.digest(password);

String encodedHash = Base64.getEncoder().encodeToString(hashed);

System.out.printf("{SHA512-CRYPT}$%s$%s", "FooBarBaz",encodedHash);

这输出散列:

{SHA512-CRYPT}$FooBarBazWPtOnXVI/a6f003WByGKIcsfa6x0ansxiyE8uEfJ0TE5pI+Rv9kcMLgdZboKg7ZSWQgWFg+pIqruvdg6aiP/g==

我也试过调换salt + password的顺序来实现:

digest.update(password);
byte[] hashed = digest.digest(salt);

这给了我:

{SHA512-CRYPT}$FooBarBaz$QWS8+W5EWhModF+uO2tcsd55tDxzdzGJ5FurIbEgwVCwKfT5UqwIvBNG1Oyws8bZEFdeGgyD0u6zS1KArvGf9Q==

有谁知道如果我使用相同的密码和盐,我怎样才能在 Java 中获得相同的散列结果?

我要查找的哈希是:

{SHA512-CRYPT}$FooBarBaz$.T.G.7FRJqZ6N2FF7b3BEkr5j37CWhwgvPOOoccrr0bvkBbNMmLCxzqQqKJbNhnhC.583dTBLEuZcDuQe7NEe.

doveadm 使用 Unix crypt family of functions to generate the hash and outputs the hash as a Base64 encoded string. The alphabet used for the encoding (by crypt) is [a-zA-Z0-9./] (as mentioned on the man page for the functions). However, the alphabet used by the java.util.Base64 class is [A-Za-z0-9+/] (compliant with RFC 4648, as mentioned on the JavaDoc page for the Base64 class)。因此,即使散列值相同,它们的编码也会不同。

一个可靠的选择是使用 Apache Commons Codec 中的 Crypt class 作为 Crypt.crypt("firstpassword", "$FooBarBaz")(前缀 $ 是强制性的,以指示 Crypt 需要使用 SHA512-CRYPT 算法)。这将生成您预期的哈希值。