Метод subtle.generateKey для ECDH

ECDH (Elliptic Curve Diffie-Hellman) — алгоритм, позволяющий двум сторонам вычислить общий секрет по открытым параметрам, не передавая сам секрет по сети. В Web Crypto API он используется через интерфейс SubtleCrypto, доступный как crypto.subtle.


Сигнатура subtle.generateKey

Метод генерации ключей имеет универсальную форму:

crypto.subtle.generateKey(
  algorithm,
  extractable,
  keyUsages
)

Для ECDH параметры имеют строго определённую структуру.


Параметры для ECDH

algorithm

Объект конфигурации алгоритма:

{
  name: "ECDH",
  namedCurve: "P-256"
}

Поддерживаемые кривые:

  • "P-256" — наиболее распространённая, баланс между безопасностью и производительностью
  • "P-384" — повышенный уровень криптографической стойкости
  • "P-521" — максимальная стойкость среди стандартных кривых, но более медленная

Выбор кривой влияет на размер ключей и вычислительную нагрузку.


extractable

true | false

Определяет, можно ли экспортировать ключи из объекта CryptoKey.

  • true — ключ можно извлечь (например, для хранения или передачи)
  • false — ключ остаётся внутри Web Crypto и не может быть экспортирован

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


keyUsages

Массив допустимых операций для ключа.

Для ECDH доступны:

  • "deriveKey" — создание симметричного ключа на основе ECDH
  • "deriveBits" — получение «сырых» байтов общего секрета

Пример:

["deriveKey", "deriveBits"]

Возвращаемое значение

Метод возвращает Promise, который разрешается в объект:

CryptoKeyPair

Структура:

{
  publicKey: CryptoKey,
  privateKey: CryptoKey
}
  • publicKey — можно передавать другой стороне
  • privateKey — должен оставаться в безопасности и не покидать контекст

Базовый пример генерации ключевой пары ECDH

const keyPair = await crypto.subtle.generateKey(
  {
    name: "ECDH",
    namedCurve: "P-256"
  },
  false,
  ["deriveKey", "deriveBits"]
);

console.log(keyPair.publicKey);
console.log(keyPair.privateKey);

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


Использование ключей в ECDH

Сгенерированная пара не используется напрямую для шифрования. Её задача — создание общего секрета с другой стороной.

Типичный поток:

  1. Генерация пары ключей у обеих сторон
  2. Обмен публичными ключами
  3. Вычисление общего секрета через deriveBits или deriveKey

Пример подготовки ключей для обмена

const aliceKeys = await crypto.subtle.generateKey(
  {
    name: "ECDH",
    namedCurve: "P-256"
  },
  false,
  ["deriveKey", "deriveBits"]
);

const bobKeys = await crypto.subtle.generateKey(
  {
    name: "ECDH",
    namedCurve: "P-256"
  },
  false,
  ["deriveKey", "deriveBits"]
);

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

Для обмена ключами публичная часть обычно экспортируется:

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

Формат "spki" используется для асимметричных публичных ключей.


Важные особенности реализации

1. Ключи не являются «текстом» или числами

CryptoKey — это объект-обёртка, внутри которого хранится материал ключа в защищённом виде.


2. Приватный ключ нельзя восстановить

Даже при наличии публичного ключа вычислить приватный невозможно при корректной реализации ECDH и использовании стандартных кривых.


3. Ключи привязаны к контексту Web Crypto

Они не сериализуются напрямую через JSON.stringify и не могут быть клонированы стандартными методами.


Ошибки при использовании generateKey с ECDH

Неверная кривая

namedCurve: "secp256k1" // не поддерживается в большинстве браузеров

Результат: NotSupportedError


Неподдерживаемые usages

["encrypt"]

ECDH не предназначен для прямого шифрования, поэтому будет ошибка.


Попытка экспорта приватного ключа при extractable = false

Даже при правильной логике:

extractable: false

экспорт приватного ключа невозможен.


Типичный сценарий использования в реальных системах

ECDH в Web Crypto API почти всегда используется как этап гибридной криптографии:

  • ECDH → генерация общего секрета
  • HKDF / PBKDF2 → производный ключ
  • AES-GCM → симметричное шифрование данных

Связка с deriveKey

Хотя generateKey создаёт пару, основной практический смысл раскрывается через:

  • subtle.deriveKey
  • subtle.deriveBits

Именно они превращают ECDH в механизм установления общего ключа шифрования.


Особенности безопасности

  • Приватный ключ должен оставаться в памяти как можно меньше времени
  • Рекомендуется использовать extractable: false
  • Повторное использование ключевых пар без необходимости снижает криптостойкость системы
  • Публичные ключи можно безопасно передавать по открытым каналам

Итоговая структура взаимодействия

  1. generateKey → создание пары ECDH
  2. exportKey (publicKey) → обмен
  3. importKey (publicKey другой стороны)
  4. deriveBits или deriveKey → общий секрет
  5. использование симметричного алгоритма (например AES-GCM)