Асимметричное шифрование (шифрование с открытым ключом) основано на использовании пары ключей: публичного (public key) и приватного (private key). Публичный ключ используется для шифрования данных, а приватный — для их расшифровки. Такая модель решает проблему безопасной передачи ключей, характерную для симметричных алгоритмов.
Основные свойства:
Наиболее распространённый алгоритм — RSA, который поддерживается библиотекой Jsrsasign.
Jsrsasign — это JavaScript-библиотека, реализующая криптографические операции:
Для шифрования с открытым ключом в Jsrsasign используется класс
RSAKey.
Jsrsasign поддерживает различные форматы представления ключей:
Пример публичного ключа в PEM:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqh...
-----END PUBLIC KEY-----
Приватный ключ:
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBg...
-----END PRIVATE KEY-----
Для работы с ключом его необходимо загрузить в объект
RSAKey.
const rsa = new KJUR.crypto.RSAKey();
rsa.readCertPEM(pubKeyPEM);
Альтернативный способ:
rsa.readPKCS8PubKeyHex(pubKeyHex);
Шифрование производится с использованием публичного ключа.
const plaintext = "Секретное сообщение";
const encryptedHex = rsa.encrypt(plaintext);
Результат возвращается в шестнадцатеричном формате (hex). Для удобства передачи его часто кодируют в Base64:
const encryptedBase64 = hextob64(encryptedHex);
RSA не предназначен для шифрования больших объёмов данных напрямую. Ограничения:
Пример ограничения:
Padding — это механизм добавления случайных данных перед шифрованием для повышения безопасности.
Jsrsasign поддерживает:
Пример использования OAEP:
const encrypted = rsa.encryptOAEP("данные", "sha256");
Параметры:
Для расшифровки используется приватный ключ:
const rsa = new KJUR.crypto.RSAKey();
rsa.readPKCS8PrvKeyHex(prvKeyHex);
const decrypted = rsa.decrypt(encryptedHex);
Если использовался Base64:
const encryptedHex = b64tohex(encryptedBase64);
const decrypted = rsa.decrypt(encryptedHex);
Jsrsasign позволяет генерировать ключи:
const keypair = KEYUTIL.generateKeypair("RSA", 2048);
const pubKeyObj = keypair.pubKeyObj;
const prvKeyObj = keypair.prvKeyObj;
Экспорт в PEM:
const pubPEM = KEYUTIL.getPEM(pubKeyObj);
const prvPEM = KEYUTIL.getPEM(prvKeyObj, "PKCS8PRV");
Практическое применение RSA — защита симметричных ключей:
Это позволяет:
Перед шифрованием важно учитывать кодировку:
const utf8Hex = utf8tohex("Пример текста");
const encrypted = rsa.encrypt(utf8Hex);
После расшифровки:
const decryptedUtf8 = hextoutf8(decryptedHex);
Типичные проблемы:
1. Переполнение блока
2. Несовпадение padding
3. Неверный формат ключа
4. Проблемы с кодировкой
Ключевые рекомендации:
// Генерация ключей
const kp = KEYUTIL.generateKeypair("RSA", 2048);
// Экспорт
const pubPEM = KEYUTIL.getPEM(kp.pubKeyObj);
const prvPEM = KEYUTIL.getPEM(kp.prvKeyObj, "PKCS8PRV");
// Импорт
const rsaPub = new KJUR.crypto.RSAKey();
rsaPub.readCertPEM(pubPEM);
const rsaPrv = new KJUR.crypto.RSAKey();
rsaPrv.readPKCS8PrvKeyHex(KEYUTIL.getHexFromPEM(prvPEM));
// Шифрование
const encrypted = rsaPub.encrypt("hello");
// Расшифрование
const decrypted = rsaPrv.decrypt(encrypted);
RSA значительно медленнее симметричных алгоритмов:
Рекомендуется:
Jsrsasign:
Web Crypto API:
Выбор зависит от требований проекта и среды выполнения.
Такая схема обеспечивает конфиденциальность и защищённость передачи данных в распределённых системах.