RSASSA-PKCS1-v1_5: алгоритм и применение

RSASSA-PKCS1-v1_5 относится к семейству RSA-алгоритмов цифровой подписи, основанных на схеме заполнения PKCS

Математическая основа и принцип работы

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

Схема RSASSA-PKCS1-v1_5 работает следующим образом:

  • исходное сообщение сначала хэшируется (например, SHA-256)
  • полученный хэш оборачивается в структуру ASN.1 DigestInfo
  • затем применяется схема заполнения PKCS#1 v1.5
  • после этого выполняется RSA-операция возведения в степень по модулю

Ключевая особенность этой схемы заключается в том, что она детерминированная: одинаковые входные данные всегда дают одинаковую подпись при одном и том же ключе.

Поддержка в Web Crypto API

В Web Crypto API алгоритм обозначается строкой:

RSASSA-PKCS1-v1_5

Он используется в трёх основных операциях:

  • генерация ключей
  • создание подписи
  • проверка подписи

Поддержка зависит от браузера, но в современных реализациях (Chrome, Firefox, Safari, Edge) алгоритм доступен стабильно.


Генерация RSA-ключевой пары

Для начала работы требуется создать ключевую пару:

const keyPair = await crypto.subtle.generateKey(
  {
    name: "RSASSA-PKCS1-v1_5",
    modulusLength: 2048,
    publicExponent: new Uint8Array([1, 0, 1]),
    hash: "SHA-256"
  },
  true,
  ["sign", "verify"]
);

Параметры:

modulusLength

  • длина модуля RSA в битах
  • минимально допустимо 2048
  • 4096 используется в более строгих сценариях

publicExponent

  • обычно фиксированное значение 65537 ([1, 0, 1])
  • баланс между безопасностью и производительностью

hash

  • алгоритм хэширования, применяемый перед подписью
  • чаще всего SHA-256, также возможны SHA-384, SHA-512

Формирование подписи

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

const encoder = new TextEncoder();
const data = encoder.encode("сообщение для подписи");

const signature = await crypto.subtle.sign(
  {
    name: "RSASSA-PKCS1-v1_5"
  },
  keyPair.privateKey,
  data
);

Результат signature представляет собой ArrayBuffer, содержащий бинарную подпись.

Особенности:

  • входные данные не хэшируются вручную — это делает WebCrypto автоматически согласно указанному hash
  • подпись зависит строго от содержимого сообщения и ключа

Проверка подписи

Проверка выполняется с использованием публичного ключа:

const isValid = await crypto.subtle.verify(
  {
    name: "RSASSA-PKCS1-v1_5"
  },
  keyPair.publicKey,
  signature,
  data
);

Результат:

  • true — подпись корректна
  • false — данные или подпись изменены, либо ключ не соответствует

Особенности PKCS#1 v1.5 padding

Схема PKCS#1 v1.5 является одной из старейших схем заполнения для RSA. Её структура фиксирована и включает:

  • байты заполнения 0x00 0x01
  • блок псевдослучайных байтов 0xFF
  • разделитель 0x00
  • ASN.1 структура хэша

Примерно:

00 01 FF FF FF ... 00 ASN.1 DigestInfo

Несмотря на широкое использование, схема считается менее устойчивой к некоторым классам атак по сравнению с RSA-PSS.


Сравнение с RSA-PSS

В Web Crypto API существует более современный вариант:

  • RSA-PSS

Ключевые различия:

RSASSA-PKCS1-v1_5

  • детерминированная подпись
  • простая реализация
  • широкая совместимость
  • исторически распространена (TLS, PKI)

RSA-PSS

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

Экспорт и импорт ключей

Web Crypto позволяет экспортировать ключи для хранения или передачи:

Экспорт публичного ключа

const exportedPublicKey = await crypto.subtle.exportKey(
  "spki",
  keyPair.publicKey
);

Экспорт приватного ключа

const exportedPrivateKey = await crypto.subtle.exportKey(
  "pkcs8",
  keyPair.privateKey
);

Полученные данные — бинарные ArrayBuffer, обычно кодируются в Base64 для хранения.


Импорт ключей

Импорт публичного ключа

const publicKey = await crypto.subtle.importKey(
  "spki",
  exportedPublicKey,
  {
    name: "RSASSA-PKCS1-v1_5",
    hash: "SHA-256"
  },
  true,
  ["verify"]
);

Импорт приватного ключа

const privateKey = await crypto.subtle.importKey(
  "pkcs8",
  exportedPrivateKey,
  {
    name: "RSASSA-PKCS1-v1_5",
    hash: "SHA-256"
  },
  true,
  ["sign"]
);

Представление данных и кодирование

Web Crypto API работает с бинарными структурами (ArrayBuffer), поэтому в реальных приложениях часто требуется кодирование:

Преобразование в Base64

function bufferToBase64(buffer) {
  const bytes = new Uint8Array(buffer);
  let binary = "";
  for (let i = 0; i < bytes.byteLength; i++) {
    binary += String.fromCharCode(bytes[i]);
  }
  return btoa(binary);
}

Обратное преобразование

function base64ToBuffer(base64) {
  const binary = atob(base64);
  const bytes = new Uint8Array(binary.length);
  for (let i = 0; i < binary.length; i++) {
    bytes[i] = binary.charCodeAt(i);
  }
  return bytes.buffer;
}

Области применения RSASSA-PKCS1-v1_5

Алгоритм широко используется в инфраструктуре, где важна совместимость:

  • TLS-сертификаты (в том числе исторические реализации)
  • цифровые подписи документов
  • JWT (в некоторых конфигурациях)
  • PKI-системы
  • проверка подлинности обновлений ПО

Использование в JWT

В JSON Web Token алгоритм обозначается как:

RS256

Это означает:

  • RSA
  • PKCS#1 v1.5 padding
  • SHA-256

Структура подписи JWT:

header.payload.signature

где signature создаётся RSA-операцией над хэшем первых двух частей.


Криптографические ограничения и риски

Несмотря на распространённость, схема имеет особенности, которые важно учитывать:

Отсутствие случайности Подпись полностью детерминирована, что упрощает некоторые атаки при ошибочной реализации протоколов.

Зависимость от правильной валидации Ошибки в проверке ASN.1 структуры могут привести к уязвимостям.

Исторические атаки на PKCS#1 v1.5 Существуют атаки на неправильно реализованные проверки подписи (например, Bleichenbacher-подобные сценарии), особенно в старых системах.


Практические особенности работы в браузере

При использовании Web Crypto API важно учитывать:

  • операции асинхронны и возвращают Promise
  • ключи нельзя извлечь, если extractable: false
  • API работает только в secure context (HTTPS или localhost)
  • поддержка Node.js требует отдельного модуля crypto.webcrypto

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

RSASSA-PKCS1-v1_5 имеет следующие характеристики:

  • генерация ключей — относительно медленная операция (особенно 4096 бит)
  • подпись — быстрее, чем RSA-PSS в некоторых реализациях
  • проверка — обычно быстрее подписи

На практике узким местом чаще является именно генерация ключей, а не операция подписи.


Типичные ошибки при использовании

Несовпадение hash-алгоритма Ключ создаётся с одним hash, а подпись выполняется с другим — приводит к невалидным результатам.

Передача строки вместо ArrayBuffer Web Crypto не принимает строки напрямую.

Повторное использование ключей с разными алгоритмами Ключ, созданный для RSASSA-PKCS1-v1_5, нельзя использовать в RSA-PSS.

Игнорирование кодировок Разные стороны системы могут использовать различное преобразование строки в байты.


Совместимость и стандарты

Алгоритм закреплён в:

  • PKCS#1 v1.5
  • RFC 8017
  • спецификациях Web Crypto API (W3C)

Он остаётся актуальным из-за огромного количества существующих систем, где замена алгоритма невозможна без миграции инфраструктуры.