Расшифрование данных закрытым ключом

Работа с асимметричным шифрованием в Jsrsasign строится вокруг модели пары ключей: открытого и закрытого. Закрытый ключ используется для восстановления исходных данных, зашифрованных соответствующим открытым ключом. В библиотеке реализована поддержка нескольких схем RSA-шифрования, включая PKCS#1 v1.5 и OAEP, что напрямую влияет на способ расшифрования.

Представление закрытого ключа

Закрытый ключ в Jsrsasign обычно представлен в формате PEM, совместимом с PKCS#1 или PKCS#8. Он содержит все необходимые параметры RSA: модуль, приватную экспоненту и дополнительные коэффициенты для ускорения операций.

Пример структуры PEM:

-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBK...
-----END PRIVATE KEY-----

Или классический RSA-формат:

-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAs...
-----END RSA PRIVATE KEY-----

Jsrsasign способен автоматически определить тип ключа при парсинге.

Загрузка закрытого ключа в объект RSA

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

const KEYUTIL = require("jsrsasign").KEYUTIL;

const privateKeyPEM = `
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBK...
-----END PRIVATE KEY-----
`;

const rsaKey = KEYUTIL.getKey(privateKeyPEM);

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

Расшифрование данных методом RSAKey

Наиболее прямой способ расшифрования — использование метода decrypt объекта RSAKey. Он применяется при классическом RSA (обычно PKCS#1 v1.5).

const encryptedBase64 = "X3J0...";

const decryptedBytes = rsaKey.decrypt(
  Buffer.from(encryptedBase64, "base64").toString("binary")
);

const decryptedText = decryptedBytes;

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

Расшифрование PKCS#1 v1.5 через KJUR.crypto.Cipher

Более высокоуровневый способ использует модуль KJUR.crypto.Cipher, который автоматически управляет преобразованиями и схемой паддинга.

const { KJUR } = require("jsrsasign");

const decrypted = KJUR.crypto.Cipher.decrypt(
  encryptedBase64,
  rsaKey,
  "RSA"
);

Данный метод упрощает работу, так как самостоятельно выполняет:

  • декодирование Base64
  • выбор схемы PKCS#1 v1.5
  • преобразование результата в строку

Расшифрование с OAEP padding

OAEP считается более безопасной схемой по сравнению с PKCS#1 v1.5 и часто используется в современных системах.

const decryptedOAEP = KJUR.crypto.Cipher.decrypt(
  encryptedBase64,
  rsaKey,
  "RSAOAEP"
);

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

Работа с бинарными данными и кодировками

Jsrsasign оперирует бинарными строками, что требует аккуратной работы при интеграции с Node.js Buffer или браузерными API.

Часто используется следующая цепочка преобразований:

const encryptedBinary = Buffer.from(encryptedBase64, "base64").toString("binary");
const decrypted = rsaKey.decrypt(encryptedBinary);

После расшифрования результат может потребовать дополнительного преобразования:

const text = Buffer.from(decrypted, "binary").toString("utf8");

Частые ошибки при расшифровании

Некорректное расшифрование в Jsrsasign чаще всего связано не с алгоритмом, а с несоответствием входных данных:

  • использование неправильного padding (PKCS#1 vs OAEP)
  • повреждённый Base64
  • несоответствие ключевой пары (шифрование выполнено другим публичным ключом)
  • попытка декодировать UTF-8 как binary без преобразования
  • передача PEM с лишними символами или пробелами

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

Расшифрование в браузере

В браузерной среде Jsrsasign работает без Node.js Buffer, поэтому преобразования выполняются через встроенные функции библиотеки:

const decrypted = KJUR.crypto.Cipher.decrypt(
  encryptedBase64,
  rsaKey,
  "RSAOAEP"
);

В отличие от серверной среды, строка Base64 передаётся напрямую без промежуточных преобразований.

Использование закрытого ключа PKCS#8 с паролем

Если ключ зашифрован, Jsrsasign позволяет указать пароль при загрузке:

const rsaKey = KEYUTIL.getKey(privateKeyPEM, "password123");

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

Взаимодействие с гибридным шифрованием

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

  1. RSA decrypt → получение AES-ключа
  2. AES decrypt → получение исходного сообщения

Jsrsasign обычно применяется только на первом этапе:

const aesKey = KJUR.crypto.Cipher.decrypt(
  encryptedKeyBase64,
  rsaKey,
  "RSAOAEP"
);

Далее полученный ключ передаётся в AES-модуль.

Особенности обработки больших данных

RSA не предназначен для шифрования больших объёмов информации. При попытке расшифровать длинные строки возникает ограничение по размеру блока, зависящее от длины ключа и типа padding. Например, для RSA-2048 с PKCS#1 v1.5 максимальный размер блока ограничен 245 байтами.

Поэтому при работе с Jsrsasign важно учитывать, что метод decrypt применяется только к коротким фрагментам данных или ключевым материалам.

Внутреннее устройство процесса расшифрования

При вызове decrypt библиотека выполняет последовательность операций:

  • преобразование входной строки в BigInteger
  • применение приватной экспоненты RSA
  • восстановление исходного блока данных
  • удаление padding (PKCS#1 или OAEP)
  • возврат результата в бинарной форме

Эти шаги скрыты от разработчика, но определяют совместимость с другими реализациями RSA (OpenSSL, WebCrypto, Java Crypto API).

Совместимость с внешними системами

Jsrsasign корректно взаимодействует с RSA-шифрованием, выполненным в:

  • OpenSSL
  • Java (javax.crypto)
  • Node.js crypto
  • Web Crypto API (при совпадении схемы padding)

Ключевым условием остаётся полное совпадение параметров:

  • длина ключа
  • алгоритм padding
  • hash function (для OAEP)

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