RSA-OAEP: принцип работы

Алгоритм RSA относится к классу асимметричных криптосистем, в которых используются две различные ключевые величины: открытый ключ (public key) и закрытый ключ (private key). Открытый ключ применяется для шифрования данных, а закрытый — для их расшифровки. Безопасность RSA основана на вычислительной сложности факторизации больших чисел.

Классическая схема RSA уязвима к ряду атак, если применяется напрямую. Для устранения этих недостатков используется специальная схема дополнения (padding), одной из наиболее надёжных является RSA-OAEP (Optimal Asymmetric Encryption Padding).


Суть и назначение RSA-OAEP

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

  • семантическую безопасность (непредсказуемость шифротекста)
  • защиту от атак с выбранным открытым текстом (CPA)
  • рандомизацию шифрования

В отличие от “голого” RSA, где одинаковые сообщения дают одинаковый шифротекст, OAEP вводит случайность, делая результат уникальным при каждом шифровании.


Архитектура OAEP

OAEP строится на основе двух криптографических примитивов:

  • хэш-функция (Hash) — например, SHA-256
  • маскирующая генераторная функция (MGF — Mask Generation Function), чаще всего MGF1

Процесс OAEP включает несколько этапов преобразования исходного сообщения перед применением RSA.


Процесс шифрования

Пусть имеется сообщение M, которое необходимо зашифровать.

1. Подготовка параметров

  • k — длина модуля RSA в байтах
  • hLen — длина хэш-функции
  • L — необязательная метка (label), чаще всего пустая строка
  • lHash = Hash(L)

2. Формирование блока данных

Создаётся строка:

DB = lHash || PS || 0x01 || M

где:

  • PS — строка из нулевых байтов
  • 0x01 — разделитель

3. Генерация случайного значения

seed = random(hLen)

4. Маскирование

  • dbMask = MGF(seed, k - hLen - 1)

  • maskedDB = DB XOR dbMask

  • seedMask = MGF(maskedDB, hLen)

  • maskedSeed = seed XOR seedMask

5. Формирование итогового блока

EM = 0x00 || maskedSeed || maskedDB

6. Шифрование RSA

C = RSA_Encrypt(EM, publicKey)

Процесс расшифровки

Расшифровка выполняется в обратном порядке:

  1. RSA-дешифрование:

    EM = RSA_Decrypt(C, privateKey)
  2. Разделение:

    • первый байт (должен быть 0x00)
    • maskedSeed
    • maskedDB
  3. Восстановление:

    • seedMask = MGF(maskedDB, hLen)

    • seed = maskedSeed XOR seedMask

    • dbMask = MGF(seed, k - hLen - 1)

    • DB = maskedDB XOR dbMask

  4. Проверка lHash

  5. Извлечение сообщения M после байта 0x01


Особенности безопасности

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

  • рандомизация: каждый шифротекст уникален
  • двойное маскирование: взаимосвязанное преобразование seed и DB
  • защита от атак на структуру: отсутствие предсказуемости

Важно, что безопасность OAEP доказана в рамках модели случайного оракула (Random Oracle Model).


Реализация RSA-OAEP в библиотеке jsrsasign

Библиотека jsrsasign предоставляет инструменты для работы с RSA и OAEP. Основной класс для шифрования — KJUR.crypto.Cipher.

Подключение библиотеки

<script src="jsrsasign-all-min.js"></script>

Шифрование с использованием RSA-OAEP

var pubKey = "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----";

var cipher = new KJUR.crypto.Cipher();
cipher.setAlg("RSAOAEP");

var plaintext = "Hello RSA-OAEP";

var encrypted = cipher.encrypt(plaintext, pubKey);
console.log(encrypted);

Расшифровка

var privKey = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----";

var cipher = new KJUR.crypto.Cipher();
cipher.setAlg("RSAOAEP");

var decrypted = cipher.decrypt(encrypted, privKey);
console.log(decrypted);

Настройка параметров OAEP

В jsrsasign можно указать используемую хэш-функцию:

cipher.setAlg("RSAOAEP", "sha256");

Поддерживаемые алгоритмы:

  • SHA-1 (по умолчанию)
  • SHA-224
  • SHA-256
  • SHA-384
  • SHA-512

Ограничения длины сообщения

Максимальный размер сообщения определяется формулой:

mLen ≤ k - 2*hLen - 2

где:

  • k — размер ключа в байтах
  • hLen — длина хэша

Например:

  • RSA 2048 бит (256 байт)
  • SHA-256 (32 байта)

Максимальная длина:

256 - 2*32 - 2 = 190 байт

Практические аспекты использования

  • RSA-OAEP применяется для шифрования малых данных, например:

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

    • данные шифруются AES
    • ключ AES шифруется RSA-OAEP

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

Использование “голого” RSA

  • отсутствие padding делает систему уязвимой

Неправильный выбор хэш-функции

  • SHA-1 устарел, предпочтительнее SHA-256+

Несоответствие параметров при шифровании и расшифровке

  • одинаковый алгоритм и хэш обязателен

Сравнение с PKCS#1 v1.5

Характеристика RSA-OAEP PKCS#1 v1.5
Безопасность Высокая Уязвим к атакам
Рандомизация Да Ограниченная
Современность Рекомендуется Устаревает

Внутренняя роль MGF1

MGF1 генерирует псевдослучайную последовательность на основе хэш-функции:

MGF1(seed, length)

Работает как конкатенация:

Hash(seed || counter)

Это позволяет создавать маски произвольной длины.


Взаимосвязь seed и DB

Ключевая особенность OAEP — циклическая зависимость:

  • seed влияет на maskedDB
  • maskedDB влияет на maskedSeed

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


Пример полной схемы

  1. Сообщение → padding OAEP
  2. OAEP-блок → RSA-шифрование
  3. Шифротекст → передача
  4. RSA-дешифрование → OAEP-блок
  5. Удаление padding → исходное сообщение

Роль случайности

Генерация seed критична для безопасности:

  • должна использоваться криптографически стойкая функция
  • повторное использование seed недопустимо

В jsrsasign используется встроенный генератор случайных чисел.


Применение в реальных протоколах

RSA-OAEP широко используется в:

  • TLS (в некоторых режимах)
  • PKCS#1 v2.2
  • WebCrypto API
  • системах обмена ключами

Производительность

RSA-OAEP медленнее симметричных алгоритмов:

  • сложные операции над большими числами
  • используется только для небольших объёмов данных

Проверки при расшифровке

При декодировании выполняются строгие проверки:

  • первый байт должен быть 0x00
  • совпадение lHash
  • наличие байта 0x01

При нарушении — ошибка, данные считаются недостоверными.


Вывод формата данных

jsrsasign возвращает результат в формате:

  • HEX (по умолчанию)
  • возможно преобразование в Base64

Пример:

var b64 = hextob64(encrypted);

Итоговая структура OAEP-блока

EM = 0x00 || maskedSeed || maskedDB

Где:

  • maskedSeed = seed XOR MGF(maskedDB)
  • maskedDB = DB XOR MGF(seed)

Такая структура обеспечивает криптографическую стойкость и защищённость от широкого спектра атак.