Что такое хеширование и зачем оно нужно

Хеширование — это процесс преобразования произвольных данных в строку фиксированной длины при помощи специального алгоритма — хеш-функции.

На вход хеш-функция может получать данные любого размера:

"password"
"123456"
"qwerty123"

На выходе всегда формируется уникальный набор символов фиксированной длины:

5e884898da28047151d0e56f8dc6292773603d0d...

Полученный результат называется:

  • хешем;
  • хеш-суммой;
  • digest-значением.

В JavaScript и Node.js хеширование применяется практически во всех системах аутентификации, авторизации и защиты данных.


Основная идея хеширования

Главная особенность хеширования заключается в том, что процесс работает только в одну сторону.

Можно:

Текст → Хеш

Нельзя:

Хеш → Исходный текст

Именно поэтому пароли в безопасных приложениях не хранятся в открытом виде.

Вместо этого сохраняется только хеш:

Пароль пользователя:
mypassword123

Сохранённый хеш:
a8b7c6d5e4...

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


Чем хеширование отличается от шифрования

Очень распространённая ошибка — путать хеширование и шифрование.

Шифрование

Шифрование предназначено для сокрытия данных с возможностью последующего восстановления.

Текст → Шифр → Текст

Для расшифровки используется ключ.

Пример:

"secret"
↓
"8fj2kf9s"
↓
"secret"

Хеширование

Хеширование не предполагает обратного преобразования.

Текст → Хеш

Вернуть исходные данные невозможно.

Пример:

"secret"
↓
"2bb80d537b..."

Свойства криптографических хеш-функций

Безопасная хеш-функция должна обладать несколькими важными свойствами.

Детерминированность

Одинаковые данные всегда дают одинаковый хеш.

hash("password")
hash("password")

Результат:

5f4dcc3b5aa765d61d8327deb882cf99

Быстрое вычисление

Алгоритм должен быстро создавать хеш даже для больших объёмов данных.

Это важно для:

  • проверки файлов;
  • сетевых протоколов;
  • баз данных;
  • кэширования.

Необратимость

Из хеша нельзя получить исходное значение.

Даже при наличии:

  • современного оборудования;
  • мощных видеокарт;
  • огромных вычислительных ресурсов.

Устойчивость к коллизиям

Коллизия — ситуация, при которой разные данные дают одинаковый хеш.

Пример плохой функции:

"abc" → 123
"xyz" → 123

Криптографическая функция должна минимизировать вероятность подобных совпадений.


Эффект лавины

Даже минимальное изменение данных полностью меняет хеш.

Пример:

password1

и

password2

дадут совершенно разные результаты.


Где используется хеширование

Хеширование применяется практически во всех областях разработки.


Хранение паролей

Самая известная область применения.

При регистрации:

Пароль → Хеш → База данных

При авторизации:

Введённый пароль → Новый хеш

После этого система сравнивает:

Хеш из БД
=
Хеш введённого пароля

Если значения совпадают — пароль верный.


Проверка целостности файлов

Хеш позволяет определить, изменился ли файл.

Пример:

archive.zip
↓
SHA-256:
a4f5b6...

После скачивания пользователь может вычислить хеш самостоятельно.

Если значения совпадают:

Оригинальный хеш = Новый хеш

значит файл не повреждён и не был изменён.


Цифровые подписи

Хеширование используется в:

  • SSL/TLS;
  • HTTPS;
  • электронных подписях;
  • сертификатах безопасности.

Вместо подписи всего файла подписывается его хеш.

Это ускоряет работу системы.


Блокчейн

В блокчейнах хеши используются для:

  • формирования цепочек блоков;
  • проверки транзакций;
  • майнинга;
  • защиты от изменений данных.

Каждый блок содержит хеш предыдущего блока.

Изменение любого блока ломает всю цепочку.


Кэширование

Хеши помогают быстро находить данные.

Например:

URL → Хеш

или:

Объект → Хеш-ключ

Это активно используется в:

  • Redis;
  • CDN;
  • браузерах;
  • системах сборки.

Хеширование в JavaScript

В JavaScript хеширование чаще всего используется на сервере через Node.js.

Для этого применяются:

  • встроенный модуль crypto;

  • библиотеки:

    • bcrypt;
    • argon2;
    • password-hash;
    • scrypt.

Почему обычного хеша недостаточно для паролей

Многие новички совершают опасную ошибку:

const crypto = require("crypto")

const hash = crypto
  .createHash("sha256")
  .update(password)
  .digest("hex")

На первый взгляд выглядит безопасно.

Но для хранения паролей это плохое решение.


Проблема скорости

SHA-256 создавался как очень быстрый алгоритм.

Современные видеокарты способны вычислять миллиарды SHA-хешей в секунду.

Это позволяет злоумышленникам массово перебирать пароли.


Атака brute force

Brute force — полный перебор всех возможных комбинаций.

Пример:

123456
123457
123458
...

Если алгоритм работает слишком быстро, пароль может быть подобран за секунды.


Словарные атаки

Злоумышленники используют базы популярных паролей:

  • qwerty;
  • 123456;
  • admin;
  • password;
  • iloveyou.

Для каждого слова заранее вычисляется хеш.

Затем выполняется сравнение с украденной базой.


Радужные таблицы

Радужная таблица — заранее подготовленная база:

Пароль → Хеш

Пример:

password → 5f4dcc3b5aa765d61d8327deb882cf99

Если пароль хранится без дополнительной защиты, подобрать его становится значительно проще.


Соль (Salt)

Salt — случайная строка, добавляемая к паролю перед хешированием.

Пример:

password + X7aP91Lm

После этого вычисляется хеш.


Зачем нужна соль

Salt решает несколько важных проблем:

Защита от радужных таблиц

Даже одинаковые пароли будут иметь разные хеши.

password + salt1
password + salt2

Результат:

a12f...
b98c...

Уникальность хешей

Два пользователя с одинаковым паролем не будут иметь одинаковые записи в базе.


Усложнение атак

Злоумышленнику приходится подбирать пароль отдельно для каждого пользователя.


Медленные алгоритмы хеширования

Для хранения паролей применяются специальные алгоритмы:

  • bcrypt;
  • scrypt;
  • Argon2;
  • PBKDF2.

Они специально работают медленно.

Это делает массовый перебор крайне дорогим.


Библиотека password-hash

Библиотека password-hash — простой инструмент для:

  • генерации хеша пароля;
  • проверки пароля;
  • автоматического использования соли.

Пример установки:

npm install password-hash

Принцип работы password-hash

Библиотека автоматически:

  1. генерирует случайную соль;
  2. объединяет пароль и соль;
  3. создаёт защищённый хеш;
  4. сохраняет служебную информацию внутри строки.

Пример результата:

sha1$3$1d00a113$e7e4dc6c2...

Внутри строки содержатся:

  • алгоритм;
  • количество итераций;
  • соль;
  • итоговый хеш.

Генерация хеша

Пример:

const passwordHash = require("password-hash")

const hashedPassword =
  passwordHash.generate("mypassword")

console.log(hashedPassword)

Результат:

sha1$3$8f9d1a$9e2c4b...

Проверка пароля

При авторизации:

const passwordHash = require("password-hash")

const verified =
  passwordHash.verify(
    "mypassword",
    storedHash
  )

console.log(verified)

Результат:

true

Почему verify безопаснее ручного сравнения

Нельзя делать так:

if (hash1 === hash2)

Некоторые типы сравнений могут быть уязвимы к timing attack.

Библиотеки проверки паролей используют специальные методы безопасного сравнения.


Итерации хеширования

password-hash поддерживает многократное повторение вычислений.

Пример:

passwordHash.generate(password, {
  iterations: 10
})

Каждая дополнительная итерация:

  • увеличивает время вычисления;
  • усложняет brute-force атаки.

Выбор алгоритма

Библиотека поддерживает:

  • sha1;
  • md5;
  • более сложные варианты через настройки.

Пример:

passwordHash.generate(password, {
  algorithm: "sha256"
})

Почему MD5 и SHA1 считаются устаревшими

Алгоритмы:

  • MD5;
  • SHA1;

имеют известные криптографические уязвимости.

Их нельзя использовать в современных системах безопасности.

Особенно опасно применять их для хранения паролей.


Современные рекомендации

В современных проектах предпочтение обычно отдаётся:

  • Argon2;
  • bcrypt;
  • scrypt.

Они обеспечивают:

  • защиту от GPU-атак;
  • высокую стоимость перебора;
  • устойчивость к современным методам взлома.

Особенности password-hash

Преимущества библиотеки:

  • простота;
  • минимальное количество кода;
  • автоматическая работа с salt;
  • быстрый старт;
  • удобная проверка паролей.

Недостатки библиотеки

Несмотря на удобство, библиотека имеет ограничения.

Устаревшие алгоритмы

По умолчанию могут использоваться алгоритмы, которые уже не считаются надёжными.


Отсутствие memory-hard защиты

Современные алгоритмы вроде Argon2 используют не только процессор, но и память.

Это значительно усложняет GPU-взлом.

password-hash такой защиты не предоставляет.


Не лучший выбор для новых проектов

Для современных production-систем чаще рекомендуют:

  • bcrypt;
  • argon2.

Пример полного цикла авторизации

Регистрация

const passwordHash = require("password-hash")

const password = "mypassword"

const hashed =
  passwordHash.generate(password)

// сохранить hashed в БД

Вход в систему

const passwordHash = require("password-hash")

const enteredPassword = "mypassword"

// получить хеш из БД
const savedHash = user.password

const verified =
  passwordHash.verify(
    enteredPassword,
    savedHash
  )

if (verified) {
  console.log("Доступ разрешён")
} else {
  console.log("Неверный пароль")
}

Типичные ошибки при работе с хешированием

Хранение паролей в открытом виде

Крайне опасный подход:

password: qwerty123

При утечке базы все аккаунты оказываются скомпрометированы.


Использование SHA256 без соли

Даже сильный алгоритм становится уязвим без salt.


Самостоятельная реализация криптографии

Нельзя писать собственные алгоритмы:

reverse(password) + "secret"

Подобные решения не являются безопасными.


Использование одинаковой соли

Salt должен быть случайным и уникальным для каждого пользователя.


Слишком маленькое число итераций

Низкая стоимость вычисления делает атаки значительно дешевле.


Что происходит внутри при проверке пароля

Этапы проверки:

  1. из строки хеша извлекается salt;
  2. извлекается алгоритм;
  3. извлекается число итераций;
  4. введённый пароль хешируется повторно;
  5. выполняется безопасное сравнение результатов.

Архитектура безопасного хранения паролей

Современная схема выглядит так:

Пароль
↓
Salt
↓
Медленный алгоритм
↓
Хеш
↓
База данных

При авторизации:

Введённый пароль
↓
Те же параметры
↓
Новый хеш
↓
Сравнение

Роль хеширования в веб-безопасности

Без хеширования невозможно представить:

  • современные сайты;
  • банковские системы;
  • облачные сервисы;
  • социальные сети;
  • API;
  • корпоративные платформы.

Практически каждая система аутентификации использует хеширование как базовый механизм защиты учётных данных.