Шифрование и расшифрование строк

Шифрование строк в Jsrsasign опирается на два основных подхода: симметричное шифрование (чаще всего AES) и асимметричное (RSA). В первом случае один и тот же ключ используется для шифрования и расшифрования, во втором — пара ключей: публичный для шифрования и приватный для расшифрования. Работа со строками требует дополнительного контроля кодировок, поскольку криптографические алгоритмы оперируют байтами, а не текстом.

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

Основные форматы представления результата:

  • Hex (шестнадцатеричный)
  • Base64
  • UTF-8 (как входной формат строки)

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


Симметричное шифрование AES

Jsrsasign предоставляет симметричное шифрование через KJUR.crypto.Cipher. AES используется как основной алгоритм для шифрования строк благодаря высокой скорости и безопасности при корректном управлении ключами.

Пример шифрования строки:

const plainText = "Секретное сообщение";
const password = "strong-password-123";

const encrypted = KJUR.crypto.Cipher.encrypt({
  alg: "aes256",
  pass: password,
  data: plainText
});

Расшифрование выполняется аналогично:

const decrypted = KJUR.crypto.Cipher.decrypt({
  alg: "aes256",
  pass: password,
  data: encrypted
});

Важные параметры AES-шифрования

  • alg — алгоритм (aes128, aes192, aes256)
  • pass — пароль или ключ
  • data — строка для обработки

Внутри библиотеки пароль преобразуется в ключ с помощью KDF (key derivation function), что позволяет использовать текстовый пароль вместо бинарного ключа.


Управление ключами в AES

Использование пароля упрощает работу, но снижает контроль над криптографической стойкостью. Более строгий подход — использование заранее сгенерированного ключа.

Пример работы с ключом:

const keyHex = "0123456789abcdef0123456789abcdef";
const data = "Конфиденциальные данные";

const encrypted = KJUR.crypto.Cipher.encrypt({
  alg: "aes256",
  key: keyHex,
  data: data,
  iv: "random-iv-value"
});

IV (Initialization Vector) используется для повышения безопасности и предотвращения одинаковых результатов при одинаковом входном тексте.


Асимметричное шифрование RSA

RSA применяется для передачи ключей и небольших сообщений. В Jsrsasign работа с RSA осуществляется через объект KEYUTIL.

Генерация или загрузка ключей:

const rsaKey = KEYUTIL.getKey(privateKeyPEM);

Публичный ключ:

const publicKey = KEYUTIL.getKey(publicKeyPEM);

Шифрование строк с RSA

Шифрование выполняется через метод encrypt:

const encrypted = publicKey.encrypt("Текст для шифрования");

Результат обычно возвращается в Base64 или Hex формате в зависимости от настроек.


Расшифрование RSA

Расшифрование доступно только с приватным ключом:

const decrypted = rsaKey.decrypt(encrypted);

RSA имеет существенное ограничение: размер входной строки ограничен длиной ключа. Например, для 2048-битного ключа максимальный размер сообщения значительно меньше 256 байт из-за padding (PKCS#1 v1.5 или OAEP).


Кодировки при RSA

При работе с RSA часто возникает необходимость явного контроля формата:

  • UTF-8 → входная строка
  • Base64 → выход шифрования
  • Hex → альтернативное представление

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


PKCS#1 padding и OAEP

RSA без padding небезопасен, поэтому Jsrsasign использует стандартные схемы заполнения:

  • PKCS#1 v1.5 — классический вариант
  • OAEP — более современный и безопасный

Пример выбора режима:

const encrypted = publicKey.encrypt("Данные", "RSA-OAEP");

Использование OAEP уменьшает риск атак на структуру шифротекста.


Смешанная схема (hybrid encryption)

Практически все реальные системы используют гибридный подход:

  • RSA шифрует только AES-ключ
  • AES шифрует основное сообщение

Схема работы:

  1. Генерация случайного AES ключа
  2. Шифрование данных через AES
  3. Шифрование AES ключа через RSA
  4. Передача двух значений

Пример:

const aesKey = "0123456789abcdef0123456789abcdef";

const encryptedData = KJUR.crypto.Cipher.encrypt({
  alg: "aes256",
  key: aesKey,
  data: "Большое сообщение"
});

const encryptedKey = publicKey.encrypt(aesKey);

Расшифрование:

const decryptedKey = privateKey.decrypt(encryptedKey);

const decryptedData = KJUR.crypto.Cipher.decrypt({
  alg: "aes256",
  key: decryptedKey,
  data: encryptedData
});

Работа с форматом результата

Jsrsasign позволяет управлять выходным форматом шифрования:

  • HEX — удобен для низкоуровневых протоколов
  • BASE64 — используется в веб-API и JSON
  • STRING — редко используется напрямую

Пример явного указания:

const encrypted = KJUR.crypto.Cipher.encrypt({
  alg: "aes256",
  pass: "password",
  data: "text",
  output: "base64"
});

Обработка ошибок при расшифровании

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

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

Jsrsasign обычно выбрасывает исключения при невозможности декодирования или при нарушении padding.


Производительность при работе со строками

AES демонстрирует линейную зависимость времени от размера строки, тогда как RSA имеет экспоненциальные ограничения на размер входных данных. Поэтому RSA используется только для коротких фрагментов.


Практика безопасной работы со строками

При проектировании криптографической логики в Jsrsasign ключевыми факторами являются:

  • фиксированная кодировка UTF-8
  • использование AES для больших данных
  • применение RSA только для обмена ключами
  • выбор OAEP вместо PKCS#1 v1.5 при возможности
  • явное управление форматом выходных данных

Обработка многострочных и JSON-строк

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

const obj = { message: "Текст", id: 123 };

const encrypted = KJUR.crypto.Cipher.encrypt({
  alg: "aes256",
  pass: "secret",
  data: JSON.stringify(obj)
});

const decrypted = JSON.parse(
  KJUR.crypto.Cipher.decrypt({
    alg: "aes256",
    pass: "secret",
    data: encrypted
  })
);

Особенности интеграции с внешними системами

При обмене данными между JavaScript и серверными реализациями RSA или AES критично совпадение:

  • padding scheme
  • длина ключа
  • режим шифрования (CBC, ECB и др.)
  • формат сериализации (Base64/Hex)

Несовпадение хотя бы одного параметра приводит к невозможности расшифрования даже при корректных ключах.