ECDSA: подпись и верификация

ECDSA (Elliptic Curve Digital Signature Algorithm) в контексте Web Crypto API реализуется через интерфейс SubtleCrypto, предоставляющий низкоуровневые операции цифровой подписи на эллиптических кривых. Основное назначение механизма — формирование криптографически устойчивой подписи сообщений и её последующая проверка с использованием публичного ключа.

ECDSA опирается на свойства эллиптических кривых и задаётся парой ключей: приватный ключ используется для формирования подписи, публичный — для проверки её корректности. В Web Crypto API работа с алгоритмом происходит через window.crypto.subtle.


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

Создание ключей осуществляется методом generateKey, где указывается алгоритм ECDSA и параметр кривой. Наиболее распространённый вариант — P-256 (также известная как secp256r1), обеспечивающая баланс между производительностью и криптостойкостью.

const keyPair = await crypto.subtle.generateKey(
  {
    name: "ECDSA",
    namedCurve: "P-256"
  },
  true,
  ["sign", "verify"]
);

Параметры генерации:

  • name: фиксированное значение "ECDSA"

  • namedCurve: выбор эллиптической кривой

    • "P-256"
    • "P-384"
    • "P-521"
  • extractable: определяет возможность экспорта ключей

  • keyUsages: набор операций, разрешённых для ключа

Результатом является объект CryptoKeyPair, содержащий:

  • privateKey
  • publicKey

Подготовка данных для подписи

ECDSA работает с бинарными данными (ArrayBuffer), поэтому текстовые данные требуют предварительного преобразования.

const encoder = new TextEncoder();
const data = encoder.encode("message for signing");

Преобразование через TextEncoder обеспечивает корректное представление UTF-8 последовательности байтов.


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

Подписание выполняется через метод sign. Важным элементом является выбор хэш-функции, которая предварительно обрабатывает данные перед применением ECDSA.

const signature = await crypto.subtle.sign(
  {
    name: "ECDSA",
    hash: { name: "SHA-256" }
  },
  keyPair.privateKey,
  data
);

Используемые компоненты:

  • алгоритм подписи: "ECDSA"
  • хэширование: "SHA-256" (наиболее распространённый вариант)
  • приватный ключ: источник криптографической подписи
  • данные: бинарный массив

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


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

Верификация выполняется методом verify, где используется публичный ключ и исходные данные.

const isValid = await crypto.subtle.verify(
  {
    name: "ECDSA",
    hash: { name: "SHA-256" }
  },
  keyPair.publicKey,
  signature,
  data
);

Результат — булево значение:

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

Процесс проверки включает:

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

Формат подписи ECDSA

Подпись, возвращаемая Web Crypto API, кодируется в формате ASN.1 DER и содержит два компонента:

  • r — первая часть подписи
  • s — вторая часть подписи

Эти значения формируются как результат вычислений над точками эллиптической кривой и хэш-значением сообщения.


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

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

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

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

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

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

Форматы:

  • spki — публичные ключи
  • pkcs8 — приватные ключи

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

const importedPublicKey = await crypto.subtle.importKey(
  "spki",
  exported,
  {
    name: "ECDSA",
    namedCurve: "P-256"
  },
  true,
  ["verify"]
);
const importedPrivateKey = await crypto.subtle.importKey(
  "pkcs8",
  exportedPrivate,
  {
    name: "ECDSA",
    namedCurve: "P-256"
  },
  true,
  ["sign"]
);

Импорт требует точного соответствия параметров алгоритма исходной конфигурации ключа.


Хэш-функция и её роль в ECDSA

В Web Crypto API ECDSA всегда используется совместно с хэшированием. Хэш-функция выполняет предварительное сжатие данных перед применением математического аппарата эллиптических кривых.

Поддерживаемые значения:

  • SHA-256
  • SHA-384
  • SHA-512

Наиболее распространённая комбинация:

  • ECDSA + P-256 + SHA-256

Ошибки и особенности реализации

Несоответствие алгоритма

При попытке проверки подписи с другим хэшем результат всегда будет отрицательным, даже при идентичных данных.

Работа с бинарными данными

ECDSA не работает с текстом напрямую. Любые строки требуют явного преобразования в ArrayBuffer.

Совместимость кривых

Подписи, созданные на одной кривой (например, P-384), не могут быть проверены ключом другой кривой (например, P-256).


Безопасные свойства реализации Web Crypto

ECDSA в Web Crypto API обладает следующими характеристиками:

  • приватные ключи не покидают криптографический контекст без экспорта
  • операции выполняются в изолированной среде браузера
  • доступ к ключевому материалу ограничен API уровня браузера
  • невозможность прямого чтения приватного ключа при extractable: false

Сценарий полного цикла подписи и проверки

const encoder = new TextEncoder();
const data = encoder.encode("secure message");

const keyPair = await crypto.subtle.generateKey(
  { name: "ECDSA", namedCurve: "P-256" },
  true,
  ["sign", "verify"]
);

const signature = await crypto.subtle.sign(
  { name: "ECDSA", hash: { name: "SHA-256" } },
  keyPair.privateKey,
  data
);

const result = await crypto.subtle.verify(
  { name: "ECDSA", hash: { name: "SHA-256" } },
  keyPair.publicKey,
  signature,
  data
);

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

ECDSA основан на дискретном логарифмировании на эллиптических кривых. Приватный ключ участвует в генерации уникального значения подписи для каждого сообщения. Публичный ключ используется для проверки математической связности параметров подписи с исходным сообщением.

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