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

Abd*_*yer 3 java sha512 dovecot

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

我使用脚本在数据库中插入散列密码.

doveadm pw -s SHA512-CRYPT -p password -r 500000
Run Code Online (Sandbox Code Playgroud)

我想使用JAVA应用程序散列密码.我发现了这个问题,我尝试使用相同的密码firstpassword和盐创建相同的结果哈希FooBarBaz.由于某种原因,我得到的哈希是不同的,虽然我使用相同的哈希算法,盐和密码.

这是我的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}$6$%s$%s", "FooBarBaz",encodedHash);
Run Code Online (Sandbox Code Playgroud)

这输出哈希:

{SHA512-CRYPT}$6$FooBarBaz$5WPtOnXVI/a6f003WByGKIcsfa6x0ansxiyE8uEfJ0TE5pI+Rv9kcMLgdZboKg7ZSWQgWFg+pIqruvdg6aiP/g==
Run Code Online (Sandbox Code Playgroud)

我也尝试交换salt +密码的顺序来实现:

digest.update(password);
byte[] hashed = digest.digest(salt);
Run Code Online (Sandbox Code Playgroud)

这给了我:

{SHA512-CRYPT}$6$FooBarBaz$QWS8+W5EWhModF+uO2tcsd55tDxzdzGJ5FurIbEgwVCwKfT5UqwIvBNG1Oyws8bZEFdeGgyD0u6zS1KArvGf9Q==
Run Code Online (Sandbox Code Playgroud)

有没有人知道如果我使用相同的密码和盐,如何在Java中完成相同的哈希结果?

我正在寻找的哈希是:

{SHA512-CRYPT}$6$FooBarBaz$.T.G.7FRJqZ6N2FF7b3BEkr5j37CWhwgvPOOoccrr0bvkBbNMmLCxzqQqKJbNhnhC.583dTBLEuZcDuQe7NEe.
Run Code Online (Sandbox Code Playgroud)

man*_*ish 6

doveadm使用Unix crypt函数系列生成散列并将散列输出为Base64编码的字符串.用于编码(by crypt)的字母表是[a-zA-Z0-9./](如函数的手册页中所述).但是,java.util.Base64该类使用的字母表是[A-Za-z0-9+/](符合RFC 4648,如Base64类JavaDoc页面所述).因此,即使散列值相同,它们也会以不同方式编码.

一个可靠的选择是使用Crypt从类Apache的百科全书编解码器Crypt.crypt("firstpassword", "$6$FooBarBaz")(前缀$6$是强制性的,以指示CryptSHA512-CRYPT算法需要被使用).这将生成您期望的哈希值.