Кратко говоря, криптографическая хеш-функция, чаще называемая просто хешем, — это математический алгоритм, который преобразует произвольный массив данных в строку фиксированной длины, состоящую из букв и цифр. При использовании одного и того же типа хеша длина этой строки остается неизменной, независимо от объема входных данных.
Хеш-функция может считаться криптостойкой только в том случае, если она удовлетворяет основным требованиям: стойкости к восстановлению хешируемых данных и стойкости к коллизиям, то есть невозможности получения одинаковых значений хеша из двух различных массивов данных. Интересно, что ни один из существующих алгоритмов формально не соответствует этим требованиям, поскольку восстановление исходных данных из хеша зависит лишь от вычислительных мощностей. Однако для некоторых продвинутых алгоритмов этот процесс может занимать крайне много времени.
Хэш-функции — это функции, которые принимают на вход данные, обычно в виде строки, и возвращают числовое значение. При многократном вызове одной и той же хэш-функции с одинаковыми входными данными она всегда будет возвращать одно и то же значение. Возвращаемое значение всегда будет находиться в определенном диапазоне, который зависит от конкретной хэш-функции: некоторые используют 32-битные целочисленные значения (от 0 до 4 миллиардов), в то время как другие могут иметь гораздо больший диапазон.
Криптографические хеш-функции являются важным и широко используемым инструментом для выполнения различных задач, таких как аутентификация, проверка целостности данных, защита файлов и даже обнаружение вредоносного ПО. Существует множество алгоритмов хеширования, которые различаются по криптостойкости, сложности, разрядности и другим характеристикам. Идея хеширования, как считается, принадлежит сотруднику IBM и появилась около 50 лет назад, с тех пор она не претерпела принципиальных изменений. Однако в настоящее время хеширование приобрело множество новых свойств и находит применение в различных областях информационных технологий.
Рассмотрим на примере. Допустим, мое имя — Brian. При преобразовании этого имени с помощью хеш-функции SHA-1 (одной из самых распространенных наряду с MD5 и SHA-2) с использованием онлайн-генератора, результат будет выглядеть так: 75c450c3f963befb912ee79f0b63e563652780f0.
Как, вероятно, скажет любой другой Брайан, это имя часто пишут с ошибками, превращая его в слово "brain" (мозг). Это настолько распространенная опечатка, что однажды я даже получил водительские права, на которых вместо моего имени было написано Brain Donohue. Но это уже другая история.
Если снова воспользоваться алгоритмом SHA-1 для слова "Brain", то оно преобразуется в строку 97fb724268c2de1e6432d3816239463a6aaf8450. Как видно, результаты значительно различаются, несмотря на то, что разница между моим именем и словом "brain" заключается всего лишь в последовательности написания двух гласных. Более того, если я преобразую свое имя, написанное со строчной буквы (brian), с помощью того же алгоритма, то результат будет совершенно другим: 760e7dab2836853c63805033e514668301fa9c47.
Эти примеры иллюстрируют, как даже небольшие изменения во входных данных могут привести к совершенно различным хеш-значениям. Это свойство, называемое "чувствительностью к изменениям", является одной из ключевых характеристик хеш-функций и делает их полезными для проверки целостности данных и аутентификации.
Вот как это выглядит, если изобразить все вышесказанное в виде схемы:
Если бы мы хотели реализовать простую имитацию хэш-функции на JavaScript, она могла бы выглядеть следующим образом:
function hash(input) {
// Простой пример хэш-функции
let hashValue = 0;
for (let i = 0; i < input.length; i++) {
hashValue += input.charCodeAt(i);
}
return hashValue % 100000; // Приводим к диапазону от 0 до 99999
}
Например, если вы забыли пароль к какому-либо онлайн-сервису, вам, скорее всего, придется воспользоваться функцией восстановления пароля. В этом случае вы не получите свой старый пароль, потому что онлайн-сервис на самом деле не хранит пароли в виде обычного текста. Вместо этого они хранят их в виде хеш-значений. Это означает, что даже сам сервис не знает, как выглядит ваш пароль. Исключение составляют случаи, когда пароль очень простой и его хеш-значение широко известно среди взломщиков. Таким образом, если вы, воспользовавшись функцией восстановления, получили старый пароль в открытом виде, это означает, что сервис не хеширует пароли, что является серьезным недостатком.
Вы можете провести простой эксперимент: попробуйте с помощью специального сайта преобразовать какой-нибудь простой пароль, например «123456» или «password», из их хеш-значений (созданных алгоритмом MD5) обратно в текст. Вероятность того, что в базе хешей найдутся данные о введенных вами простых паролях, очень высока. В моем случае хеши слов «brain» (8b373710bcf876edd91f281e50ed58ab) и «Brian» (4d236810821e8e83a025f2a83ea31820) успешно распознались, а вот хеш предыдущего абзаца — нет. Это отличный пример для тех, кто все еще использует простые пароли.
Еще один интересный пример: недавно в новостях обсуждали случай, когда популярный облачный сервис Dropbox заблокировал одного из своих пользователей за распространение контента, защищенного авторскими правами. Пользователь сразу же написал об этом в Twitter, вызвав волну недовольства среди других пользователей, которые начали обвинять Dropbox в том, что он якобы просматривает содержимое клиентских аккаунтов, хотя не имеет на это права.
На самом деле необходимость в этом не была. Дело в том, что владелец защищенного контента имел хеш-коды определенных аудио- и видеофайлов, запрещенных к распространению, и занес их в список блокируемых хешей. Когда пользователь попытался незаконно распространить контент, автоматические сканеры Dropbox обнаружили файлы, чьи хеши совпадали с хешами из этого списка, и заблокировали возможность их распространения.