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

Работа расшифровки в CryptoJS чаще всего ломается не из-за самого алгоритма, а из-за несоответствия входных данных, кодировок и параметров шифрования. При этом API библиотеки не всегда явно сообщает причину ошибки — результатом может быть пустая строка, «кракозябры» или исключение при преобразовании UTF-8.

Несовпадение алгоритма шифрования

Одной из базовых проблем становится использование разных алгоритмов на этапе шифрования и расшифровки.

На практике встречаются ситуации:

  • шифрование выполнено AES-256, а расшифровка идёт как AES-128
  • используется CBC-режим при шифровании, но при расшифровке предполагается ECB
  • на одной стороне используется CryptoJS, на другой — OpenSSL или WebCrypto с другими дефолтами

CryptoJS по умолчанию применяет AES в режиме CBC с PKCS7 padding. Если исходные данные были зашифрованы иначе, результат расшифровки будет некорректным даже при правильном ключе.


Ошибки ключа и пароля

Ключ — наиболее частая причина некорректной расшифровки.

Типичные проблемы:

  • ключ отличается хотя бы на один символ
  • используется строка вместо WordArray без корректного преобразования
  • пароль и ключ перепутаны местами
  • разные кодировки ключа (UTF-8 vs Latin1)

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

  • "123456" и "123456 " (лишний пробел)
  • использование CryptoJS.enc.Utf8.parse(key) на одной стороне и «сырой строки» на другой

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


Ошибки кодировки результата расшифровки

Расшифровка в CryptoJS часто выглядит корректной, но при преобразовании в строку ломается.

Типичная конструкция:

CryptoJS.AES.decrypt(ciphertext, key).toString()

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

Правильный вариант:

CryptoJS.AES.decrypt(ciphertext, key).toString(CryptoJS.enc.Utf8)

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

  • пустая строка
  • набор символов «â˜ºâ˜»
  • обрезанный текст
  • корректный текст только для ASCII-символов

Неверный формат ciphertext

CryptoJS ожидает строго определённый формат входных данных.

Распространённые ошибки:

  • передаётся объект вместо строки Base64
  • используется hex, но не указан формат при расшифровке
  • строка повреждена при передаче через URL или JSON
  • потеря padding символов = в Base64

Пример проблемы:

  • корректно: U2FsdGVkX1...=
  • некорректно: U2FsdGVkX1... (обрезан =)

Также часто встречается ошибка при использовании URL-safe Base64, где + и / заменяются на - и _.


Проблемы с salt и OpenSSL-форматом

CryptoJS поддерживает OpenSSL-совместимый формат:

Salted__ + salt + ciphertext

Если шифрование выполнялось с использованием CryptoJS.AES.encrypt(...).toString(), то внутри уже встроен salt.

Ошибка возникает, когда:

  • расшифровка выполняется как «чистый AES», без учета salt
  • данные передаются без префикса Salted__
  • используется сторонний OpenSSL-шифротекст без совместимого derivation

Следствие — ключ генерируется иначе, и расшифровка невозможна.


Ошибки IV (Initialization Vector)

В режиме CBC критично наличие IV.

Типичные проблемы:

  • IV не передан при расшифровке
  • IV отличается от использованного при шифровании
  • IV случайно пересоздаётся каждый раз
  • IV хранится вместе с данными, но неправильно извлекается

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

  • шифрование: CryptoJS.AES.encrypt(data, key, { iv })
  • расшифровка: IV не передан → результат мусор

Важно: даже при правильном ключе отсутствие IV полностью ломает результат.


Неверный режим шифрования (mode)

CryptoJS поддерживает несколько режимов:

  • CBC (по умолчанию)
  • ECB
  • CFB
  • OFB

Ошибка возникает, если:

  • шифрование в CBC, расшифровка в ECB
  • один код использует явное указание mode, другой нет

Пример скрытой ошибки:

mode: CryptoJS.mode.ECB

при расшифровке без этого параметра приводит к полностью некорректному результату.


Padding-ошибки

По умолчанию используется PKCS7 padding.

Проблемы:

  • шифрование без padding, расшифровка с PKCS7
  • нестандартный padding (ZeroPadding, NoPadding)
  • повреждение последнего блока ciphertext

Симптомы:

  • ошибка Malformed UTF-8 data
  • обрезанный текст
  • лишние символы в конце строки

Ошибки при использовании WordArray

CryptoJS работает через внутренний тип WordArray, но часто передаются строки напрямую.

Типичные ошибки:

  • передача ключа как string без CryptoJS.enc.Utf8.parse
  • попытка decrypt с raw string ciphertext
  • неправильная конвертация hex/base64

Неверно:

CryptoJS.AES.decrypt(ciphertext, "key")

Корректно:

CryptoJS.AES.decrypt(ciphertext, CryptoJS.enc.Utf8.parse("key"))

Проблемы двойного кодирования

Частая логическая ошибка:

  • данные уже Base64
  • затем они снова кодируются в Base64 или URL encode

Результат:

  • расшифровка получает «двойной слой»
  • итог — мусорные данные

Особенно часто встречается при передаче через JSON API или query string.


Ошибки JSON и сериализации

Если ciphertext передаётся как часть JSON:

  • кавычки экранируются
  • символы + и / изменяются
  • происходит обрезка строки

Типичный случай:

{ "data": "U2FsdGVkX1+abc/==" }

после обработки может стать:

{ "data": "U2FsdGVkX1 abc " }

Результат — невозможность расшифровки.


Несовместимость браузера и Node.js

Хотя CryptoJS является универсальной библиотекой, поведение может отличаться:

  • различия в реализации random bytes
  • особенности Buffer vs WordArray
  • отличия в обработке UTF-8

Частая ошибка:

  • шифрование в Node.js через Buffer
  • расшифровка в браузере через CryptoJS без адаптации формата

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

Даже корректно зашифрованные данные могут быть повреждены:

  • обрезка строки на сервере
  • лимиты URL длины
  • неправильное хранение в базе (TEXT vs VARCHAR)
  • автоматическое удаление = или +

Симптомы:

  • ошибка без явного исключения
  • пустая строка на выходе
  • частично читаемый текст

Отсутствие явных ошибок CryptoJS

Особенность CryptoJS — отсутствие строгой валидации.

Вместо исключения часто возвращается:

  • пустая строка
  • некорректный текст
  • WordArray с нулевым содержимым

Это приводит к ложному ощущению «успешной расшифровки».


Системные причины некорректного результата

На практике большинство проблем сводится к нескольким категориям:

  • различие параметров шифрования (mode, padding, iv)
  • ошибки кодировки (UTF-8, Base64, hex)
  • повреждение ciphertext при передаче
  • неправильная работа с ключами и derivation
  • несовместимость реализаций между системами

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