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

Одна из самых частых проблем при работе с Iron возникает при попытке расшифровать ранее сериализованный объект. Сообщение об ошибке вида Integrity check failed означает, что контроль целостности данных не пройден.

Причины:

  • Использован другой password, отличный от того, который применялся при Iron.seal
  • Изменены параметры iron options (например, encryption, integrity, ttl)
  • Повреждена строка токена (обрезание, лишние символы, переносы строк)
  • Попытка расшифровки данных, которые не были созданы через Iron

Типичный пример неправильного использования:

const sealed = await Iron.seal({ user: 'alex' }, 'secret1', Iron.defaults);

// позже
const unsealed = await Iron.unseal(sealed, 'secret2', Iron.defaults);

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


Ошибка: Bad hmac value

Ошибка появляется на этапе проверки HMAC (контрольной подписи данных).

Основные причины:

  • Изменение сериализованной строки вручную
  • Передача токена через систему, которая модифицирует символы (+, /, = в base64)
  • Неверное кодирование при транспортировке (например, URL без encodeURIComponent)
  • Несовпадение параметров salt, password или encryption

Особенно часто проблема возникает при передаче токена через query string:

const url = `/session?token=${sealed}`;

Если не использовать кодирование:

encodeURIComponent(sealed)

строка может быть интерпретирована неправильно, и HMAC проверка провалится.


Ошибка: несоответствие ttl и истечение времени

Iron поддерживает временные ограничения через параметр ttl (time to live). При его использовании данные автоматически становятся недействительными.

Симптомы:

  • Iron.unseal возвращает ошибку истечения срока
  • Данные не восстанавливаются даже при правильном пароле

Причины:

  • Превышен ttl (в миллисекундах)
  • Системное время сервера отличается от времени создания токена
  • Используется распределённая система без синхронизации времени

Пример проблемной конфигурации:

const options = {
  ttl: 1000 * 60 * 5 // 5 минут
};

Если сервер и клиент имеют разницу во времени даже в несколько минут, токены становятся недействительными раньше ожидаемого срока.


Ошибка: Unexpected token при unseal

Возникает на этапе десериализации JSON после расшифровки.

Причины:

  • Передан невалидный токен (не результат Iron.seal)
  • Повреждение строки при хранении в базе данных
  • Двойное кодирование JSON (например, JSON.stringify выполнен дважды)

Пример ошибки:

const bad = "\"{\\\"user\\\":\\\"alex\\\"}\"";

После расшифровки получается строка, которая не соответствует ожидаемому JSON.


Ошибка: несовпадение алгоритмов и опций Iron

Iron использует набор криптографических параметров по умолчанию. Любое расхождение между seal и unseal приводит к невозможности восстановления данных.

Частые ошибки:

  • Разные Iron.defaults в разных частях системы
  • Изменение encryption (например, aes-256-cbc vs aes-128-cbc)
  • Несовпадение iterationCount и saltBits

Пример:

const optionsA = { encryption: 'aes-256-cbc' };
const optionsB = { encryption: 'aes-128-cbc' };

Даже при одинаковом пароле данные становятся несовместимыми.


Ошибка: использование Buffer вместо строки

Iron ожидает корректный формат входных данных. Передача Buffer без преобразования часто приводит к непредсказуемому поведению.

Проблемный случай:

const data = Buffer.from(JSON.stringify({ user: 'alex' }));

await Iron.seal(data, password, Iron.defaults);

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

Корректный подход — явное приведение:

JSON.stringify({ user: 'alex' })

Ошибка: изменение порядка параметров seal и unseal

Iron строго зависит от согласованности параметров. Перестановка аргументов приводит к полной несовместимости.

Типичная ошибка:

Iron.seal(data, options, password);

вместо:

Iron.seal(data, password, options);

Такая ошибка не вызывает синтаксическую ошибку JavaScript, но полностью ломает криптографическую структуру результата.


Ошибка: неправильная работа с многоуровневым JSON

При вложенных структурах часто происходит потеря типов данных.

Сценарии:

  • Объекты с Date превращаются в строки
  • undefined удаляется при сериализации
  • Map и Set теряют структуру

После unseal восстановленный объект отличается от исходного, хотя криптографически операция успешна.

Пример:

const original = {
  date: new Date(),
  map: new Map([['a', 1]])
};

После восстановления:

  • date становится строкой
  • map превращается в пустой объект или теряет структуру

Ошибка: конфликт версий библиотеки Iron

Разные версии Iron используют несовместимые внутренние алгоритмы сериализации.

Симптомы:

  • Токены, созданные в одной версии, не читаются в другой
  • Ошибки Bad hmac value или Integrity check failed

Особенно критично при:

  • миграции проекта
  • микросервисной архитектуре
  • смешении зависимостей в монорепозитории

Ошибка: повторное шифрование уже зашифрованных данных

Попытка повторного применения Iron.seal к уже зашифрованной строке приводит к разрушению структуры данных.

Сценарий:

const first = await Iron.seal(data, password, Iron.defaults);
const second = await Iron.seal(first, password, Iron.defaults);

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


При сохранении sealed-строки часто возникают проблемы с экранированием.

Причины:

  • ограничение длины cookie
  • автоматическое удаление символов браузером
  • некорректная сериализация при установке заголовков HTTP

Особенно часто страдают символы:

  • ;
  • =
  • +

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