ECDH (Elliptic Curve Diffie–Hellman) представляет собой механизм установления общего секрета между двумя сторонами через открытый канал связи без предварительного обмена секретами. В основе лежит математика эллиптических кривых, позволяющая получать одинаковый результат у двух участников при обмене публичными ключами, при этом восстановить приватные ключи или общий секрет из перехваченных данных вычислительно крайне затруднительно.
В Web Crypto API реализация ECDH доступна через интерфейс
SubtleCrypto, предоставляющий низкоуровневые
криптографические операции в браузере и некоторых runtime-средах,
поддерживающих стандарт Web Crypto.
Протокол строится вокруг пары ключей:
Каждая сторона генерирует собственную пару ключей. После обмена публичными ключами происходит вычисление общего секрета:
S = f(privA, pubB)S = f(privB, pubA)Благодаря свойствам эллиптических кривых значения совпадают:
S_A = S_B.
В SubtleCrypto ECDH использует параметр
namedCurve. Наиболее распространённые значения:
P-256 (secp256r1)P-384P-521Каждая кривая определяет уровень криптографической стойкости и
производительность. На практике чаще всего используется
P-256 как баланс между безопасностью и скоростью.
Создание ключей выполняется через
crypto.subtle.generateKey.
const keyPair = await crypto.subtle.generateKey(
{
name: "ECDH",
namedCurve: "P-256"
},
false,
["deriveKey", "deriveBits"]
);
Параметры:
name: "ECDH" — указывает алгоритмnamedCurve — выбранная эллиптическая криваяextractable: false — ключ нельзя экспортировать
(повышение безопасности)keyUsages — допустимые операции, чаще всего
deriveKey и deriveBitsРезультат содержит:
keyPair.publicKeykeyPair.privateKeyДля передачи публичного ключа используется экспорт в формат JWK или SPKI.
const exportedPublicKey = await crypto.subtle.exportKey(
"jwk",
keyPair.publicKey
);
JWK (JSON Web Key) удобен для передачи через API или хранение в JSON.
const importedPublicKey = await crypto.subtle.importKey(
"jwk",
exportedPublicKey,
{
name: "ECDH",
namedCurve: "P-256"
},
true,
[]
);
Импортированный ключ может использоваться для вычисления общего секрета.
Основная операция ECDH — получение общего массива байтов.
const sharedBits = await crypto.subtle.deriveBits(
{
name: "ECDH",
public: importedPublicKey
},
keyPair.privateKey,
256
);
Параметры:
public — публичный ключ второй стороныprivateKey — собственный приватный ключlength — длина результата в битахРезультат sharedBits — ArrayBuffer,
содержащий криптографический секрет.
Часто результат ECDH не используется напрямую. Вместо этого он применяется для генерации симметрического ключа (например AES-GCM).
const aesKey = await crypto.subtle.deriveKey(
{
name: "ECDH",
public: importedPublicKey
},
keyPair.privateKey,
{
name: "AES-GCM",
length: 256
},
false,
["encrypt", "decrypt"]
);
Такой подход позволяет сразу получить ключ для симметричного шифрования без ручной обработки байтового массива.
Процесс установления общего секрета включает последовательность шагов:
Важно, что приватные ключи никогда не покидают устройство.
Web Crypto API использует несколько стандартных форматов:
raw — бинарный формат (для некоторых кривых)jwk — JSON Web Keyspki — публичный ключ X.509pkcs8 — приватные ключиECDH в браузере чаще всего опирается на jwk, поскольку
он легко сериализуется.
Несмотря на математическую стойкость, безопасность зависит от корректного использования API:
deriveKey вместо прямого
deriveBitsP-256 или вышеОбщий секрет ECDH обычно не используется напрямую, поскольку он не имеет равномерного распределения для симметричных алгоритмов. Для нормализации применяется HKDF.
Пример цепочки:
const baseKey = await crypto.subtle.importKey(
"raw",
sharedBits,
"HKDF",
false,
["deriveKey"]
);
const derivedKey = await crypto.subtle.deriveKey(
{
name: "HKDF",
hash: "SHA-256",
salt: new Uint8Array([]),
info: new Uint8Array([])
},
baseKey,
{
name: "AES-GCM",
length: 256
},
false,
["encrypt", "decrypt"]
);
Web Crypto API работает в контексте безопасности:
ECDH реализован аппаратно или через оптимизированные библиотеки платформы, что обеспечивает высокую производительность.
На практике часто возникают следующие проблемы:
Обе стороны должны использовать одинаковую кривую:
ECDH требует строго ключей типа CryptoKey с алгоритмом
"ECDH".
Некоторые реализации ожидают фиксированную длину ключа, что требует нормализации через KDF.
ECDH редко используется изолированно. Он является частью более сложных протоколов:
Во всех случаях ECDH отвечает только за установку общего секрета, а дальнейшая криптография строится на симметричных алгоритмах.
Внутреннее представление ключа скрыто, но логически можно выделить:
ECDH)namedCurve)public/private)keyUsages)extractable)Эта модель унифицирует работу с различными криптографическими алгоритмами через единый API.
Кривые влияют на скорость:
На клиентских устройствах чаще выбирается P-256 из-за производительности и широкого аппаратного ускорения.
ECDH часто комбинируется с:
Так формируются полноценные гибридные криптосистемы, где ECDH отвечает за безопасную передачу ключевого материала, а симметричные алгоритмы — за основную нагрузку шифрования данных.