Шифрование и расшифровка RSA

Генерируйте пары ключей RSA в браузере, шифруйте и расшифровывайте по RSA-OAEP, подписывайте по RSA-PSS или PKCS#1 v1.5, конвертируйте ключи между форматами PEM SPKI, PKCS#8 и PKCS#1. Всё работает локально на движке WebCrypto — ни ключ, ни сообщение никогда не покидают эту страницу.
Для чего нужен RSA: для коротких сообщений и подписей, а не для больших объёмов данных. RSA шифрует не больше k−2·hashLen−2 байт за вызов (190 байт для ключа 2048 бит с SHA-256) и примерно в 1000 раз медленнее AES. Настоящие системы используют гибридное шифрование: RSA оборачивает случайный ключ AES, AES шифрует данные (см. инструмент AES). Эта страница существует для обучения, тестирования и проверок совместимости.
Размер модуля:
Хеш: Метка:
PKCS#1 v1.5 шифрование намеренно не реализовано: у него нет целостности шифртекста, и оно уязвимо к атакам padding oracle (Блейхенбахер). OAEP — единственный режим шифрования, который стоит использовать в новых решениях.
Схема: Хеш:
Схема: Хеш:
Сколько может переносить один вызов RSA? Предел сообщения OAEP = байты ключа − 2×байты хеша − 2:
МодульSHA-256SHA-384SHA-512
1024 бит62 байта30 байт0 байт
2048 бит190 байт126 байт62 байта
3072 бита318 байт254 байта190 байт
4096 бит446 байт382 байта318 байт
У подписей нет предела сообщения — сообщение сначала хешируется; сама подпись всегда ровно размера ключа (256 байт для 2048 бит).
Стойкость ключа и срок службы (NIST SP 800-57 Part 1 Rev. 5): 1024 бита запрещены для нового использования с 2013 года; 2048 бит — минимум на сегодня и допустимы до 2030 года; 3072 бита и больше — комфортный выбор для 2031 года и далее. 8192 бита здесь работают, но генерация в браузере может занять минуту и больше, а защиты, которая никому сейчас не нужна, почти не добавляет — предпочитайте 3072/4096.
Совместимость с OpenSSL — PEM, которые создаёт эта страница, проходят туда и обратно в командной строке:
openssl pkeyutl -encrypt -pubin -inkey pub.pem -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256
openssl pkeyutl -decrypt -inkey priv.pem -pkeyopt rsa_padding_mode:oaep ...
openssl dgst -sha256 -sign priv.pem -out msg.sig msg.txt (PKCS#1 v1.5)  /  openssl dgst -sha256 -verify pub.pem -signature msg.sig msg.txt
PSS: добавьте -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:32 к обоим вызовам dgst. Конвертация формата ключа: openssl rsa -in key.pem -RSAPublicKey -out pubkey.pem переводит SPKI ↔ PKCS#1 на диске; эта страница делает то же в браузере.
Самопроверка
Запускает движок страницы против независимых эталонов: создание ключей трёх размеров модуля, циклы шифрования и расшифровки OAEP, подписи и проверка PSS и PKCS#1 v1.5 для разных хешей, детерминированный вектор подписи v1.5 байт в байт (сгенерирован независимой нативной реализацией), фиксированный шифртекст OAEP и подпись PSS, созданные OpenSSL, которые эта страница обязана расшифровать и проверить (проверка совместимости реализаций), циклы конвертации форматов PEM и негативные тесты (подделанная подпись и неверный ключ должны не проходить). Ничего никуда не отправляется.
Шифрование и подписи RSA с нуля
Вкратце: RSA — криптография с открытым ключом: любой может зашифровать для вас открытым ключом или проверить ваши подписи, но расшифровать или подписать может только закрытый ключ; стойкость основана на том, что разложить 2048-битное число на два простых множителя не под силу ни одному существующему компьютеру.
Что на самом деле вычисляет RSA

Два простых числа и лазейка. Ключ RSA начинается с двух больших случайных простых чисел p и q; их произведение n (модуль, отсюда «ключ 2048 бит») публикуется в открытом ключе вместе с экспонентой e (почти всегда 65537). Закрытый ключ — пара d, модульная обратная к e −, вычисленная из p и q, плюс сокращения, выведенные из простых чисел, которые ускоряют операции с закрытым ключом в 4×.

Шифрование и подпись — одно и то же возведение в степень. Шифрование блока сообщения m означает вычисление me mod n; расшифровка — cd mod n. Подпись заранее оформленного блока закрытой экспонентой и проверка открытой — та же операция в обратную сторону. Всё остальное на этой странице — OAEP, PSS, PKCS#1 — про безопасное оформление этого блока, чтобы сырое возведение в степень никогда не было открыто.

Почему это медленно. Одна операция RSA на ключе 2048 бит стоит примерно в миллион раз больше процессорного времени, чем шифрование одного блока AES. Поэтому TLS использует RSA (или ECC) только чтобы согласовать случайный ключ AES, а потом переходит на него. То же правило относится к любой вашей системе: RSA для ключа, AES для данных.

Размер ключа. Длина модуля — ручка безопасности: 1024 бита взломаны по политике (разложение почти по силам государствам), 2048 бит ≈ 112 бит симметричной стойкости, 3072 бита ≈ 128 бит, 15360 бит соответствовали бы 256-битному симметричному ключу. Замечание о постквантовом мире: алгоритм Шора полностью ломает RSA на большом квантовом компьютере — ещё одна причина держать сроки службы ключей конечными.

OAEP: единственный режим шифрования, который стоит использовать

Проблема сырого RSA. Учебный RSA (me mod n от сырого сообщения) детерминирован и податлив: одинаковые сообщения шифруются одинаково, злоумышленник может умножить шифртекст на шифртекст двойки, чтобы удвоить открытый текст, а короткие сообщения падают методом встречи посередине. Его никогда нельзя использовать напрямую.

Что делает OAEP. OAEP (PKCS#1 v2, RFC 8017) перемешивает сообщение со случайным семенем через сеть Фейстеля на основе хеша перед возведением в степень. Результат: шифрование рандомизировано (один и тот же открытый текст даёт каждый раз другой шифртекст — запустите пример OAEP дважды и сравните), подделка обнаруживается при расшифровке, а сообщение должно помещаться внутри модуля с местом под хеш — предел k−2·hashLen−2, указанный в таблице выше.

Метка. Необязательная публичная строка, связываемая в дополнение. Обе стороны должны указать одну и ту же метку, иначе расшифровка не удастся — как AAD в AES-GCM, она позволяет привязать шифртекст к контексту (имени файла, идентификатору алгоритма). Пустая метка — нормальный случай.

Шифрование PKCS#1 v1.5 намеренно отсутствует. Дополнение 1993 года не имеет целостности и утекает информацию через поведение ошибок расшифровки (атака Блейхенбахера 1998 года превращает оракул дополнения в полную расшифровку за несколько миллионов специально подобранных шифртекстов; она всё ещё ломает реальные системы как ROBOT, 2017). WebCrypto отказывается это реализовывать; так же поступает и эта страница.

PSS против подписей PKCS#1 v1.5

Подпись = хеш, затем дополнение, затем возведение в степень. Обе схемы хешируют сообщение (здесь SHA-256/384/512), оформляют дайджест в блок и применяют закрытую экспоненту. Проверка переоформляет блок открытым ключом и сравнивает. Разница — в оформлении:

СхемаСодержимое блокаСвойства
RSASSA-PKCS1-v1_5дайджест + заголовок digest-info, детерминированныйКаждая подпись одного и того же сообщения побайтно идентична (проверьте самопроверку: её вектор v1.5 фиксирован). Универсальная поддержка в наследии: сертификаты X.509, JWT RS*, TLS до 1.3. Известной подделки при корректно реализованной проверке нет.
RSA-PSSдайджест + случайная соль длиной с хеш, маскирование MGF1Рандомизирована — каждая подпись отличается. Доказуемо стойка в модели случайного оракула; требуется в сертификатах TLS 1.3 и более новых протоколах. Проверяющий должен знать длину соли (эта страница использует длину хеша, стандартный выбор по умолчанию).

Что выбрать. Для новых решений: PSS. Для совместимости с существующими сертификатами, JWT (RS256) или старыми узлами: v1.5. Обе схемы безопасны как схемы подписи — история катастрофы v1.5 касается *шифровального* дополнения, другой конструкции, несмотря на похожее название.

PKCS#1 против PKCS#8 против SPKI: почему у одного ключа четыре PEM

PEM — это просто base64 в обёртке DER. Файл PEM — метка плюс base64 структуры DER (двоичный ASN.1). Метка говорит, какая это структура, и это вся разница между четырьмя форматами, которые создаёт эта страница:

Метка PEMСтруктура DERСодержит
-----BEGIN PUBLIC KEY-----SubjectPublicKeyInfo (SPKI)OID алгоритма + открытый ключ (n, e). Стандартный «открытый ключ» везде.
-----BEGIN RSA PUBLIC KEY-----PKCS#1 RSAPublicKeyТолько (n, e). Старый OpenSSL и некоторые встраиваемые стеки.
-----BEGIN PRIVATE KEY-----PKCS#8 PrivateKeyInfoOID алгоритма + закрытый ключ. Контейнер, не зависящий от алгоритма, — современный стандарт.
-----BEGIN RSA PRIVATE KEY-----PKCS#1 RSAPrivateKeyn, e, d, p, q, …. Классический вывод genrsa OpenSSL.

Один ключ, разные обёртки. Все четыре блока выше после «Создать» содержат один и тот же ключ: SPKI и открытый PKCS#1 содержат одинаковые n, e; PKCS#8 и закрытый PKCS#1 содержат одинаковые закрытые значения. Эта страница конвертирует между ними без потерь в браузере (её самопроверка проверяет конвертации циклом). Путаница форматов — самая частая причина ошибок «invalid key» при вставке ключей между инструментами.

Зашифрованные PEM (-----BEGIN ENCRYPTED PRIVATE KEY-----) — это PKCS#8 с уровнем шифрования на основе пароля. Эта страница их не принимает — сначала расшифруйте офлайн (openssl pkcs8 -in enc.pem -out plain.pem).

Распространённые ошибки
  • Шифрование больших объёмов данных RSA. Помимо жёсткого предела размера OAEP, это абсурдно медленно. Шаблон такой: создайте случайный ключ AES, зашифруйте ключ AES по RSA-OAEP, данные зашифруйте AES-GCM, отправьте обе части.
  • Выпуск закрытого ключа, потому что «это тест». Примеры ключей, встроенные в векторы этой страницы, опубликованы намеренно — они могут подписывать только тестовые данные. Ваши ключи таковыми не являются.
  • Проверка закрытым ключом. Обычно это «работает» математически, и некоторые инструменты это разрешают, но выдача закрытого ключа проверяющим разрушает всю модель. Проверяйте открытым ключом (эта страница так и требует).
  • Сравнение подписей побайтно для проверки кода. PSS (и OAEP) рандомизированы: два правильных запуска дают разные результаты. Сравнивайте проверкой, а не равенством — только подписи v1.5 детерминированы.
  • Ключи 1024 бита «потому что быстрее». Они также доступны хорошо финансируемой факторизации. Аргумент о скорости умер вместе с гибридным шифрованием: RSA выполняется один раз за сессию, а не за каждый байт.
  • Жёсткая фиксация длины соли для PSS, отличной от длины хеша. Проверяющий должен согласиться; длина хеша (выбор этой страницы и -sigopt rsa_pss_saltlen:32 в OpenSSL) — совместимый по умолчанию.
Частые вопросы

Почему расшифровка не удалась с сообщением «wrong key, wrong hash or corrupted ciphertext»? Расшифровка OAEP не удаётся, если выполняется одно из условий: это не соответствующий закрытый ключ, хеш отличается от стороны шифрования, метка отличается или изменён байт шифртекста. Ошибка намеренно одинакова во всех случаях — показать, какая проверка не прошла, само по себе утечка оракула дополнения.

Можно ли получить открытый ключ из закрытого? Да — закрытые форматы тоже содержат n и e. Эта страница показывает оба после «Создать»; OpenSSL делает это командой openssl pkey -in priv.pem -pubout.

Почему 65537 как экспонента? Это простое число, оно содержит только два единичных бита (быстрое возведение в степень) и достаточно велико, чтобы избежать атак с малой экспонентой, которые бьют e=3. Это стандартный выбор с 1990-х; «странная» экспонента обычно значит слабый или нестандартный ключ.

RSA мёртв из-за квантовых компьютеров? Пока нет — такой машины, которая бы запускала алгоритм Шора на модуле 2048 бит, не существует. Но данные, которые должны оставаться в тайне до 2030-х и далее, уже переводят на новые схемы; гибридные постквантовые схемы — инженерный ответ.

А что с openssl rsautl? Это устаревший предок pkeyutl. По умолчанию он использует дополнение шифрования v1.5 — ещё одна причина, по которой его вывели из употребления.