2015-07-14 8 views
4

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

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

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

Я хочу использовать пароли с использованием приложения JAVA. Я нашел this questions, и я попытался создать тот же полученный хеш, используя тот же пароль 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. 
+0

Я предполагаю, что sha генерирует случайные хэши для одних и тех же строк и солей. Вам просто нужно проверить их с помощью встроенных функций проверки – waplet

+1

@waplet, это неверно. Тот же вход = тот же хеш, это одно из основных требований каждого алгоритма хеширования. Кроме того, операционная система запрашивает явно, как создавать эти хэши, а не проверять их. – bratkartoffel

ответ

5

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

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

+0

Спасибо, мнимый .. не могли бы вы также добавить в свой ответ, что можно указать количество итераций «раундов» .. с помощью 'Crypt.crypt (« firstpassword »,« $ 6 $ rounds = 123123 $ FooBarBaz »)' I уже пробовал, и он отлично работает – Abdulrahman

+0

Это не только другой алфавит, функция crypt() использует алгоритм, основанный на дайджесте SHA-512, но также учитывает значение соли, а затем делает несколько тысяч раундов SHA-512 просто для того, чтобы сделать его медленнее и, таким образом, грубо заставлять менее вероятно. Использование Apache Commons Codec Crypt.crypt() - правильное решение nevertheles! – lathspell

+0

Вы, сэр, безопаснее в жизни! Одной выдержки недостаточно, чтобы выразить свою благодарность. Так что ожидайте больше этого ;-) – GhostCat