как SHA512-CRYPT для Dovecot в JAVA?

У меня есть сервер Dovecot с базой данных MySQL для хранения имен пользователей и паролей. Пароли в базе данных находятся в схеме SHA512-CRYPT.

Я вставляю хешированные пароли в базу данных с помощью скрипта.

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

Я хочу хэшировать пароли с помощью приложения 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);

Это выводит хеш:

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

Я также попытался поменять порядок соли + пароль, чтобы сделать это:

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

это дает мне:

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

Кто-нибудь знает, как я могу добиться тех же результатов хеширования в Java, если я использую тот же пароль и соль?

Хэш, который я ищу, это:

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

person Abdulrahman Alsoghayer    schedule 14.07.2015    source источник
comment
Я предполагаю, что sha будет генерировать случайные хэши для тех же строк и солей. Вам просто нужно проверить их, используя встроенные функции проверки   -  person waplet    schedule 14.07.2015
comment
@waplet, это неправда. Тот же ввод = тот же хеш, это одно из основных требований каждого алгоритма хеширования. Кроме того, оператор явно спрашивает, как создавать эти хэши, а не проверять их.   -  person bratkartoffel    schedule 14.07.2015


Ответы (1)


doveadm использует семейство функций Unix crypt для создания хэша и выводит хэш в виде строки в кодировке Base64. Алфавит, используемый для кодирования (по crypt), равен [a-zA-Z0-9./] (как указано на справочной странице для функций). Однако класс java.util.Base64 использует алфавит [A-Za-z0-9+/] (совместимый с RFC 4648, как указано в страница JavaDoc для класса Base64). Следовательно, даже если хешированные значения одинаковы, они будут кодироваться по-разному.

Надежным вариантом является использование класса Crypt из кодека Apache Commons в качестве Crypt.crypt("firstpassword", "$6$FooBarBaz") (префикс $6$ является обязательным, чтобы указать Crypt, что необходимо использовать алгоритм SHA512-CRYPT). Это сгенерирует ожидаемое значение хеш-функции.

person manish    schedule 14.07.2015
comment
Спасибо, чувак.. не могли бы вы также добавить в свой ответ, что можно указать количество итераций раундов.. с Crypt.crypt("firstpassword", "$6$rounds=123123$FooBarBaz") я уже пробовал, и он отлично работает - person Abdulrahman Alsoghayer; 14.07.2015
comment
Это не только другой алфавит, функция crypt() использует алгоритм, основанный на дайджесте SHA-512, но также принимает во внимание значение соли, а затем выполняет несколько тысяч циклов SHA-512 только для того, чтобы сделать его медленнее и, следовательно, перебором. - принуждение менее вероятно. Тем не менее, использование кодека Apache Commons Crypt.crypt() является правильным решением! - person lathspell; 14.07.2015
comment
Вы, сэр, спасаете жизнь! Одного плюса недостаточно, чтобы выразить мою благодарность. Так что ждите большего ;-) - person GhostCat; 24.01.2017
comment
На основе вашего ответа я создал простой веб-сервис для генерации хэшей Dovecot: passwordhasher.projecttac.com - person Tarator; 09.05.2019