如何在 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
算法)。这将生成您预期的哈希值。
我有一个带 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
算法)。这将生成您预期的哈希值。