Алгоритм RSA основан на сложности факторизации больших чисел и работает с парой ключей: открытым (public key) и закрытым (private key). Открытый ключ используется для шифрования или проверки подписи, закрытый — для расшифрования или создания подписи.
Схема PKCS#1 v1.5 — это исторически одна из первых стандартизированных схем дополнения (padding) для RSA. Она применяется как в шифровании, так и в цифровых подписях, но имеет различия в формате в зависимости от назначения:
Padding необходим, поскольку «чистый» RSA детерминирован и уязвим к атакам. Дополнение добавляет случайность и структурирует данные перед операцией возведения в степень.
Перед шифрованием сообщение преобразуется в блок фиксированной длины, равной длине модуля RSA (например, 2048 бит = 256 байт):
EM = 0x00 || 0x02 || PS || 0x00 || M
Где:
0x00 — обязательный начальный байт0x02 — тип блока (указывает на шифрование)PS — псевдослучайная последовательность байтов (не
содержит нулей), длина ≥ 8 байт0x00 — разделительM — исходное сообщениеКлючевые свойства:
Для подписи используется иной формат:
EM = 0x00 || 0x01 || PS || 0x00 || T
Где:
0x01 — тип блока (подпись)PS — последовательность байтов 0xFFT — DER-кодированная структура, содержащая хэш и
идентификатор алгоритмаСтруктура T включает:
В отличие от шифрования, здесь нет случайности — подпись детерминирована для одного и того же сообщения и ключа.
Библиотека jsrsasign предоставляет реализацию RSA с поддержкой PKCS#1 v1.5.
const rsa = new KJUR.crypto.Cipher();
const encrypted = rsa.encrypt("message", publicKey, "RSA");
Под капотом:
Сообщение кодируется в байты
Добавляется padding по PKCS#1 v1.5
Выполняется операция:
C = M^e mod nconst decrypted = rsa.decrypt(encrypted, privateKey, "RSA");
Процесс:
Выполняется:
M = C^d mod nПроверяется структура padding
Извлекается исходное сообщение
const sig = new KJUR.crypto.Signature({"alg": "SHA256withRSA"});
sig.init(privateKey);
sig.updateString("data");
const signature = sig.sign();
sig.init(publicKey);
sig.updateString("data");
const isValid = sig.verify(signature);
Несмотря на широкое распространение, схема PKCS#1 v1.5 имеет ряд серьёзных криптографических проблем.
Одна из наиболее известных атак на RSAES-PKCS1-v1_5, опубликованная в 1998 году.
Суть:
Атака относится к классу adaptive chosen-ciphertext attack (CCA2).
Причина уязвимости:
0x00 || 0x02Если система сообщает, корректен ли padding, возникает «оракул»:
padding valid → одна веткаpadding invalid → другая веткаЭто позволяет по частям восстанавливать сообщение.
Даже косвенные различия (время ответа, разные ошибки) могут использоваться как канал утечки.
PKCS#1 v1.5 не гарантирует полной защиты от:
Современные требования требуют IND-CCA2 безопасности, которой эта схема не обеспечивает.
Максимальная длина сообщения:
k - 11 байт
Где k — длина ключа в байтах.
Пример:
Причина:
Использование в TLS (устаревшие версии) Ранние версии TLS (до 1.2) применяли PKCS#1 v1.5 → уязвимость к Bleichenbacher
Неправильная обработка ошибок
Отсутствие защиты от повторных атак
Небезопасные реализации
Рекомендуется вместо PKCS#1 v1.5 для шифрования.
Преимущества:
В jsrsasign:
const encrypted = rsa.encrypt("message", publicKey, "RSAOAEP");
Замена RSASSA-PKCS1-v1_5 для подписей.
Особенности:
Тем не менее, в новых системах использование не рекомендуется.
Если использование PKCS#1 v1.5 неизбежно:
В jsrsasign:
При расшифровке:
0x00)0x02)0x00 после PSЛюбое отклонение:
PKCS#1 v1.5 не удовлетворяет:
Но обеспечивает:
PKCS#1 v1.5 — важный этап в развитии криптографии:
Современные системы стремятся к отказу от него в пользу более безопасных схем, но понимание принципов его работы остаётся критически важным для анализа безопасности и поддержки легаси-инфраструктуры.