3
votes

I have a Dovecot server with MySQL database for storing usernames and passwords. The passwords in the database are in SHA512-CRYPT scheme.

I am inserting the hashed passwords in the database using a script.

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

I want to hash the passwords using a JAVA application. I found this questions and I tried to create the same resulting hash using same password firstpassword and salt FooBarBaz. For some reason the resulting hash I get is different, although I am using the same hashing algorithm, salt and password.

Here is my Java code:

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);

This outputs the hash:

{SHA512-CRYPT}$6$FooBarBaz$5WPtOnXVI/a6f003WByGKIcsfa6x0ansxiyE8uEfJ0TE5pI+Rv9kcMLgdZboKg7ZSWQgWFg+pIqruvdg6aiP/g==

I also tried swapping the order of salt + password to make it:

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

this gives me:

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

Does anyone have any idea how can I accomplish the same hash results in Java if I use the same password and salt?

The hash I am looking for is:

{SHA512-CRYPT}$6$FooBarBaz$.T.G.7FRJqZ6N2FF7b3BEkr5j37CWhwgvPOOoccrr0bvkBbNMmLCxzqQqKJbNhnhC.583dTBLEuZcDuQe7NEe.
1
I guess, sha will generate random hashes for same strings and salts. You just have to check them using builtin check functionswaplet
@waplet that's not true. Same input = same hash, that's one basic requirement of every hashing algorithm. Furthermore, the op asks explicitly how to create those hashes, not to check them.bratkartoffel

1 Answers

6
votes

doveadm uses the 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). Therefore, even if the hashed values are the same, they will get encoded differently.

A reliable option is to use the Crypt class from Apache Commons Codec as Crypt.crypt("firstpassword", "$6$FooBarBaz") (The prefix $6$ is mandatory to instruct Crypt that the SHA512-CRYPT algorithm needs to be used). This will generate your expected hash value.