Содержание

В веб-проекте шифрование нужно на трёх уровнях: при передаче данных — HTTPS везде, включая внутренние соединения; при хранении — шифрование дисков, резервных копий и файлового хранилища; и на уровне отдельных полей базы — для паспортных данных, токенов и другой особо чувствительной информации. Пароли при этом не шифруют, а хешируют. Самое сложное в шифровании — не алгоритмы, а безопасное хранение ключей.

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

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

Шифрование при передаче защищает данные, пока они идут по сети: от браузера до сервера, от приложения до базы, от сервиса к сервису. Шифрование при хранении защищает данные, которые лежат на дисках, в резервных копиях и хранилищах, — на случай кражи диска, утечки бэкапа или доступа к хранилищу.

Уровень Что защищает Как реализуют
При передаче Перехват трафика HTTPS/TLS для сайта, API, базы и внутренних сервисов
Диски и тома Кражу или утилизацию дисков Шифрование дисков у провайдера или в ОС
Резервные копии Утечку бэкапов Шифрование архивов, ключ отдельно от копий
Поля базы Доступ к базе через SQL-инъекцию или дамп Шифрование в приложении перед записью
Файлы Утечку хранилища Шифрование на стороне сервера или приложения

Почему пароли хешируют, а не шифруют?

Пароли хешируют, потому что их никогда не нужно расшифровывать: при входе достаточно сравнить хеш введённого пароля с сохранённым. Зашифрованный пароль можно расшифровать, если украден ключ, а хеш — нельзя. Использовать нужно медленные алгоритмы с солью, а не быстрые вроде MD5 или SHA-256.

// Регистрация: сохраняем только хеш (bcrypt или argon2id)
$user->password = Hash::make($request->password);

// Вход: сравниваем введённый пароль с хешем
if (! Hash::check($request->password, $user->password)) {
    throw ValidationException::withMessages(['email' => 'Неверный логин или пароль']);
}

Медленные алгоритмы bcrypt и argon2id делают перебор утёкших хешей очень дорогим. Ещё надёжнее — не хранить пароли вовсе и перейти на passkeys, подробнее в статье двухфакторная аутентификация и passkeys.

Кодовый замок на клавиатуре ноутбука Фото: Unsplash

Какие поля стоит шифровать в базе?

Отдельно шифровать в базе стоит данные, утечка которых особенно опасна и которые не нужны для поиска и сортировки: паспортные данные, ИНН и СНИЛС, медицинскую информацию, токены доступа к сторонним сервисам, секретные ключи пользователей. Тогда даже полный дамп базы без ключа будет бесполезен.

Что учесть:

  1. Поиск. По зашифрованному полю нельзя искать — для точного поиска храните отдельный хеш с секретом.
  2. Сортировка и отчёты. Зашифрованные значения нельзя сортировать и группировать в SQL.
  3. Ключ вне базы. Ключ хранится в менеджере секретов или переменных окружения, а не рядом с данными.
  4. Версия ключа. Вместе с данными сохраняйте идентификатор ключа — это упрощает ротацию.

Номера банковских карт лучше не хранить вовсе: их принимает платёжный провайдер, а у вас остаётся только токен. Подробнее — в статьях как подключить онлайн-оплату и разработка финтех-продукта.

Как управлять ключами шифрования?

Ключ шифрования ценнее самих данных: тот, у кого есть ключ и доступ к базе, прочитает всё. Поэтому ключи хранят отдельно от данных, выдают только тем сервисам, которым они нужны, и регулярно меняют.

  • храните ключи в менеджере секретов или облачной службе управления ключами, а не в коде;
  • используйте разные ключи для разных окружений и разных типов данных;
  • журналируйте использование ключей;
  • отработайте ротацию: новый ключ, перешифрование, отзыв старого;
  • обеспечьте резервное копирование ключей — без ключа зашифрованные бэкапы не восстановить.

Подробнее о хранении — статья секреты в проекте.

Что проверить в своём проекте?

Минимальный набор проверок занимает пару часов и закрывает самые распространённые проблемы. Его стоит пройти перед запуском и после крупных изменений инфраструктуры.

  • HTTPS на всех доменах с перенаправлением с HTTP и заголовком HSTS;
  • TLS между приложением и базой, кешем и очередями, если они на разных серверах;
  • шифрование дисков и резервных копий включено;
  • пароли хешируются bcrypt или argon2id;
  • чувствительные поля зашифрованы, ключ хранится отдельно;
  • персональные данные не попадают в логи — подробнее в статье персональные данные на сайте.

Коротко

  • Шифруйте данные при передаче, при хранении и на уровне особо чувствительных полей.
  • Пароли хешируют медленными алгоритмами с солью, а не шифруют.
  • Шифрование полей мешает поиску и сортировке — шифруйте только то, что действительно нужно.
  • Ключи хранят отдельно от данных, с журналом доступа и отработанной ротацией.
  • Номера карт не храните вовсе — пусть их принимает платёжный провайдер.

Частые вопросы

  • Замедляет ли шифрование работу сайта?

    Практически нет. Современные процессоры шифруют аппаратно, а TLS 1.3 и HTTP/2 даже ускоряют загрузку по сравнению со старыми протоколами. Шифрование полей добавляет микросекунды на запись.

  • Можно ли искать по зашифрованным полям?

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

  • Что делать, если ключ шифрования утёк?

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