Атака на RSA PKCS#1 v1.5 (Bleichenbacher)

RSA-шифрование как математическая операция само по себе не обеспечивает семантическую безопасность без корректного форматирования сообщения. Для этого используется схема заполнения PKCS#1 v1.5, которая преобразует исходные данные перед возведением в степень по модулю RSA.

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

EM = 0x00 || 0x02 || PS || 0x00 || M

где:

  • 0x00 0x02 — фиксированные байты, обозначающие режим шифрования
  • PS — случайная непустая строка заполнения (padding string), состоящая из ненулевых байтов
  • 0x00 — разделитель
  • M — полезная нагрузка (сообщение)

Ключевой момент заключается в том, что корректность структуры становится проверяемым свойством. Любое отклонение от формата может быть обнаружено при расшифровании.


Поведение RSA-дешифрования и появление оракула

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

M = RSA_decrypt(C)

реализация должна:

  1. Выполнить RSA-операцию
  2. Проверить структуру PKCS#1 v1.5
  3. Вернуть сообщение или ошибку

Если система различает:

  • «корректный padding»
  • «некорректный padding»

то возникает утечка информации.

Такой механизм называется padding oracle — источник бинарной информации о корректности структуры сообщения.


Суть атаки Bleichenbacher

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

Основная идея:

  • имеется зашифрованный блок C
  • система сообщает, валиден ли PKCS#1 v1.5 padding после расшифровки
  • атакующий подбирает множители s, формируя новые шифртексты:
C' = (C * s^e) mod n
  • при расшифровке:
M' = (M * s) mod n
  • если padding корректен, это даёт информацию об интервале возможных значений M

Итеративное сужение диапазона сообщения

Атака строится на постепенном сокращении интервала:

[M_min, M_max]

Каждый успешный oracle-запрос позволяет уточнить границы, используя математические свойства RSA:

  • линейность по модулю
  • предсказуемую структуру padding
  • проверку диапазона 0x00 0x02 ...

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


Почему PKCS#1 v1.5 особенно уязвим

Слабость схемы заключается в том, что корректность легко проверяется:

  • фиксированные байты 0x00 0x02
  • обязательный разделитель 0x00
  • ограничения на padding string

Любая реализация, которая возвращает различимые ошибки, фактически реализует oracle.


Jsrsasign и RSA PKCS#1 v1.5

Библиотека Jsrsasign реализует RSA через объекты:

  • RSAKey
  • KJUR.crypto.Cipher
  • KEYUTIL

Пример типичного использования:

const rsa = new RSAKey();
rsa.generate(2048, "10001");

const ciphertext = rsa.encrypt("secret");
const plaintext = rsa.decrypt(ciphertext);

При использовании PKCS#1 v1.5 padding:

  • библиотека проверяет структуру вручную
  • выбрасывает ошибки при несоответствии
  • может различать типы ошибок (padding vs format vs length)

Потенциально опасное поведение в JS-реализациях

В JavaScript-окружении проблема усиливается:

  • нет строгой изоляции времени выполнения
  • исключения легко наблюдаемы
  • различия в error message доступны напрямую
  • нет аппаратной защиты от side-channel атак

Уязвимость появляется, если:

try {
    const msg = rsa.decrypt(ciphertext);
} catch (e) {
    if (e.message.includes("decryption error")) {
        // различимое поведение
    }
}

или если:

  • функция возвращает null при ошибке padding
  • либо выбрасывает исключение только для некорректных блоков

Упрощённая модель padding oracle в JSrsasign

Псевдологика уязвимого дешифрования:

function decrypt(ciphertext) {
    const m = rsaRawDecrypt(ciphertext);

    if (!m.startsWith("\x00\x02")) {
        throw new Error("padding error");
    }

    return stripPadding(m);
}

Такое поведение уже создаёт бинарный оракул:

  • success → padding valid
  • exception → padding invalid

Как Bleichenbacher эксплуатирует JS-реализацию

Атака строится на многократных запросах:

  1. Выбирается множитель s
  2. Формируется новый ciphertext
  3. Проверяется результат расшифровки
  4. По ответу корректируется диапазон возможных значений

В JavaScript это реализуется как цикл:

while (!solved) {
    const s = findNextMultiplier();
    const c2 = (c * modExp(s, e, n)) % n;

    if (oracle(c2)) {
        narrowInterval(s);
    }
}

Где oracle() — функция, основанная на поведении decrypt.


Влияние временных утечек

Даже если исключения не различаются, остаются:

  • разное время обработки padding error
  • разные ветки кода при проверке структуры
  • оптимизации интерпретатора V8

Это превращает даже «мягкую» проверку в утечку информации.


Современные последствия атаки

Исторически атака была критичной для:

  • SSL/TLS с RSA PKCS#1 v1.5
  • старых серверных реализаций
  • embedded криптографии

Современные библиотеки стараются исключать:

  • прямой доступ к padding validation
  • различимые ошибки дешифрования

Безопасные альтернативы в криптосистемах

Основная замена PKCS#1 v1.5:

OAEP (Optimal Asymmetric Encryption Padding)

Преимущества:

  • рандомизированная структура
  • отсутствие детерминированной проверки шаблона
  • невозможность построения классического oracle

В RSA это выглядит как:

RSA-OAEP(message) → ciphertext

и не допускает частичной проверки структуры.


Проблемы использования RSA в клиентском JavaScript

Использование Jsrsasign в браузере создаёт дополнительные риски:

  • атакующий контролирует среду выполнения
  • можно перехватывать исключения
  • можно модифицировать функцию decrypt
  • можно проводить активный oracle-эксперимент

Таким образом, RSA в клиентском JS не должен использоваться для расшифрования секретов, особенно с PKCS#1 v1.5.


Практические аспекты защиты в реализациях

Критические требования к безопасной реализации:

  • единообразные сообщения об ошибках
  • отсутствие различий между типами ошибок дешифрования
  • запрет PKCS#1 v1.5 для новых систем
  • использование OAEP
  • отсутствие observable side-channel различий

Пример более безопасного поведения:

function decrypt(ciphertext) {
    try {
        return rsa.decryptOAEP(ciphertext);
    } catch (e) {
        throw new Error("decryption failed");
    }
}

Причины устойчивости атаки Bleichenbacher

Атака остаётся актуальной из-за сочетания факторов:

  • математическая структура RSA
  • детерминированный формат PKCS#1 v1.5
  • возможность адаптивных запросов
  • наличие бинарного oracle-интерфейса

Даже частичная реализация этих условий в JavaScript-криптографии приводит к уязвимостям.


Модель угроз для Jsrsasign

При анализе безопасности следует учитывать:

  • выполнение в недоверенной среде (браузер)
  • доступ атакующего к API вызовам
  • возможность измерения времени выполнения
  • перехват промежуточных значений ciphertext

Любая реализация RSA decrypt в такой среде должна рассматриваться как потенциально наблюдаемая функция, а значит — как источник утечек при PKCS#1 v1.5.