13 февраля 2020
Тэги: Java, Spring, алгоритмы.
MD5 хэш (Message Digest 5) – это 128 битный алгоритм вычисления хэша от сообщения произвольной длины. Чаще всего хэш вычисляется от строки (для проверки паролей) и от файла (для контроля его целостности).
Следует сразу же заметить, что хранение паролей в виде md5-хэшей в настоящее время считается небезопасным, т.к. md5-хэш довольно сильно подвержен коллизиям. Коллизией называется ситуация, когда у двух исходных сообщений хэши равны. То есть для успешного прохождения проверки пароля, сохраняемого в виде md5-хэша, вам даже не обязательно знать именно этот пароль. Достаточно знать пароль, имеющий такой же хэш. Более того, хэши от простых паролей можно напрямую искать в Google.
Алгоритм хэширования MD5 является частью стандартной библиотеки Java, поэтому вычислить хэш от строки (например, от пароля) достаточно легко.
Тут мы используем стандартный класс MessageDigest, который по имени алгоритма возвращает его реализацию. Если алгоритм по имени не найден, то метод getInstance() кидает исключение NoSuchAlgorithmException. Поскольку мы передаём в него константу «MD5», то точно знаем, что такой ошибки не возникнет. Поэтому обрачиваем это проверяемое исключение в RuntimeException, которое является непроверяемым, чтобы не «портить» сигнатуру метода.
Затем преобразуем исходную строку, от которой требуется посчитать хэш, в массив байт. Затем передаём этот массив в метод update(). В результате он возвращает хэш также в виде массива байт. Для удобства отображения массива байт в виде строки, напишем вспомогательный метод bytesToHex().
Тут мы каждый байт преобразуем в строку, выполняя побитовое объединение этого байта с байтом 0xff. Во избежания создания лишних экземпляров строк, конкатенацию результата делаем с помощью StringBuilder, который в конце преобразуем в строку.
Байты в виде строки представляются в шестнадцатеричной (hexadecimal) системе счисления, поэтому содержат цифры от 0 до 9 и буквы от a до f.
Теперь вычислим хэш:
Если вы используете Spring, то всё то же самое можно сделать в одну строчку с помощью метода DigestUtils.md5DigestAsHex().
Для контроля целостности файла можно вычислить его хэш, а затем сравнить с заранее известным. Вычислить хэш можно следующим образом:
Для чтения файла создаём InputStream в конструкции try-with-resources, которая автоматически закроет этот поток по завершению работы с ним. Сам поток получаем с помощью метода Files.newInputStream(). Затем в цикле считываем данные в созданный нами буфер – массив байт фиксированного размера. На каждой итерации вызываем метод update() для вычисления нового хэша на основе данных из буфера и прошлого значения хэша. Затем аналогично предыдущему примеру получаем значение хэша в виде массива байт и выводим его в виде строки.
Теперь передав в метод полный путь до проверяемого файла вы можете быстро вычислить его хэш. Если у вас Linux, то для проверки значения хэша можете использовать утилиту md5sum.
Kotlin, Java, Spring, Spring Boot, Spring Data, SQL, PostgreSQL, Oracle, Linux, Hibernate, Collections, Stream API, многопоточность, файлы, Nginx, Apache, maven, gradle, JUnit, YouTube, новости, руководство, ООП, алгоритмы, головоломки, rest, GraphQL, Excel, XML, json, yaml.
05.05.2023 11:47 Elisey
Великолепная статья. Еле нашел преобразование строки в строковый хеш.