ECDH-ES и эфемерные ключи

ECDH-ES (Elliptic Curve Diffie-Hellman Ephemeral Static) — механизм согласования ключа, используемый в спецификации JWE (JSON Web Encryption) в экосистеме JOSE. Он основан на эллиптической криптографии и предназначен для безопасного формирования общего симметричного ключа между отправителем и получателем без его прямой передачи.

В отличие от классических схем шифрования, где используется заранее распределённый симметричный ключ или RSA-шифрование ключа, ECDH-ES реализует модель key agreement, в которой итоговый ключ вычисляется обеими сторонами независимо.


Основные принципы работы ECDH-ES

ECDH-ES строится на классическом алгоритме Диффи—Хеллмана на эллиптических кривых:

  • каждая сторона имеет пару ключей: приватный и публичный;
  • публичные ключи могут быть известны заранее или передаваться в сообщении;
  • общий секрет вычисляется как результат скалярного умножения приватного ключа одной стороны на публичный ключ другой.

Z = d_A Q_B = d_B Q_A

где:

  • ( d_A, d_B ) — приватные ключи сторон A и B,
  • ( Q_A, Q_B ) — соответствующие публичные ключи,
  • ( Z ) — общий секрет (shared secret).

Полученный общий секрет далее не используется напрямую как ключ шифрования. Он проходит через KDF (Key Derivation Function), чтобы получить симметричный ключ для алгоритмов вроде AES-GCM.


ECDH-ES в контексте JOSE (JWE)

В спецификации JOSE алгоритм ECDH-ES применяется как alg в заголовке JWE:

  • ECDH-ES — прямое использование общего секрета как источника ключа;
  • ECDH-ES+A128KW, ECDH-ES+A256KW — использование общего секрета для обёртки (key wrapping) контентного ключа.

В библиотеке JavaScript Jose (например, jose от Panva) этот механизм реализован через модуль JWE.


Роль эфемерных ключей

Эфемерные ключи — временные ключевые пары, генерируемые для одной операции шифрования.

В ECDH-ES они играют ключевую роль:

  • отправитель создаёт эпhemeral key pair;
  • публичная часть передаётся вместе с зашифрованным сообщением;
  • приватная часть уничтожается после операции;
  • получатель использует свой постоянный ключ и эфемерный публичный ключ для вычисления общего секрета.

Ключевая характеристика:

каждое сообщение использует уникальный набор ключей

Это обеспечивает:

  • прямую секретность (forward secrecy);
  • невозможность расшифровки старых сообщений при компрометации долгосрочного ключа;
  • отсутствие повторного использования ключевого материала.

Структура JWE с ECDH-ES

Типичная структура JWE при использовании ECDH-ES:

  • Protected Header
  • Encrypted Key (часто пустой при чистом ECDH-ES)
  • Initialization Vector (IV)
  • Ciphertext
  • Authentication Tag

В заголовке:

{
  "alg": "ECDH-ES",
  "enc": "A256GCM",
  "epk": {
    "kty": "EC",
    "crv": "P-256",
    "x": "...",
    "y": "..."
  }
}

epk — ephemeral public key, передаваемый отправителем.


Механизм вычисления ключа в ECDH-ES

Процесс можно разделить на этапы:

1. Генерация эфемерной пары ключей

Отправитель создаёт временную EC-пару:

  • private ephemeral key
  • public ephemeral key

2. Обмен публичными ключами

Получателю передаётся:

  • ephemeral public key (epk)
  • зашифрованное сообщение

3. Вычисление общего секрета

Получатель использует:

  • свой приватный ключ
  • публичный ephemeral ключ

и вычисляет shared secret.

4. Derivation Function (KDF)

Общий секрет преобразуется через KDF:

  • алгоритм: Concat KDF (из NIST SP 800-56A)
  • входные параметры: алгоритм шифрования, длина ключа, дополнительные данные

Результат:

  • Content Encryption Key (CEK)

ECDH-ES без key wrapping

В режиме чистого ECDH-ES (alg: "ECDH-ES") происходит прямое получение CEK:

  • нет отдельного encrypted key поля;
  • ключ для AES получается напрямую из KDF.

Это делает схему более компактной, но менее гибкой.


ECDH-ES с key wrapping

В вариантах:

  • ECDH-ES+A128KW
  • ECDH-ES+A256KW

процесс разделяется:

  1. ECDH + KDF → shared key
  2. shared key → используется для обёртки CEK
  3. CEK → используется для AES-GCM шифрования

Такой подход позволяет:

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

Реализация в библиотеке jose (JavaScript)

Библиотека jose реализует ECDH-ES через API JWE:

Генерация ключей

import { generateKeyPair } from 'jose';

const { publicKey, privateKey } = await generateKeyPair('ECDH-ES', {
  crv: 'P-256'
});

Шифрование с ECDH-ES

import { CompactEncrypt } from 'jose';

const encoder = new TextEncoder();

const jwe = await new CompactEncrypt(
  encoder.encode('secret data')
)
  .setProtectedHeader({
    alg: 'ECDH-ES',
    enc: 'A256GCM'
  })
  .encrypt(publicKey);

Дешифрование

import { compactDecrypt } from 'jose';

const { plaintext } = await compactDecrypt(jwe, privateKey);

console.log(new TextDecoder().decode(plaintext));

Эфемерные ключи в jose

В библиотеке jose генерация ephemeral key происходит автоматически при шифровании.

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

  • ключ не сохраняется;
  • включается в JWE header как epk;
  • используется строго один раз;
  • соответствует требованиям RFC 7518.

При необходимости ручного контроля можно использовать более низкоуровневые API generateKeyPair.


Безопасность ECDH-ES

Ключевые свойства безопасности:

  • Forward secrecy: компрометация приватного ключа не раскрывает старые сообщения;
  • Semantic security: каждый обмен использует уникальный ephemeral key;
  • Resistance to key reuse attacks: повторное использование ключей исключено на уровне протокола;
  • No key transmission: общий секрет никогда не передаётся по сети.

Слабые места возникают при:

  • неправильной реализации KDF;
  • повторном использовании ephemeral keys;
  • отсутствии проверки публичных ключей.

Отличие от RSA-based JWE

Свойство RSA ECDH-ES
Модель key transport key agreement
Эфемерные ключи нет да
Forward secrecy отсутствует присутствует
Нагрузка выше ниже
Масштабируемость хуже лучше

Использование в реальных сценариях

ECDH-ES применяется в JOSE-системах, где требуется:

  • обмен сообщениями между клиентами без предварительного общего секрета;
  • безопасная передача данных через API;
  • защищённые каналы в распределённых системах;
  • мобильные и web-приложения с динамическими ключами.

Особенности интеграции с EC-кривыми

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

  • P-256
  • P-384
  • P-521
  • X25519 (в современных версиях)

Выбор кривой влияет на:

  • производительность;
  • криптографическую стойкость;
  • совместимость с другими системами.

Взаимодействие ECDH-ES и AES-GCM

После derivation ключа используется AEAD-шифрование:

  • AES-128-GCM
  • AES-256-GCM

C = (K_{CEK}, P, IV)

где:

  • (K_{CEK}) — ключ, полученный из ECDH-ES,
    1. — plaintext,
    1. — вектор инициализации,
    1. — ciphertext.

Роль KDF в общей схеме

KDF является критическим элементом:

  • предотвращает прямое использование raw ECDH shared secret;
  • нормализует ключ под требования AES;
  • добавляет контекст (alg, apu, apv).

Используемая функция:

  • Concat KDF (RFC 7518 / NIST SP 800-56A)

Практические особенности использования jose

При работе с ECDH-ES в jose важны детали:

  • алгоритм alg должен совпадать у обеих сторон;
  • enc определяет симметричный шифр;
  • ключи должны быть EC-совместимыми;
  • ephemeral key всегда включается в header автоматически.

Ошибки чаще всего возникают при:

  • несовпадении кривых;
  • неправильной сериализации ключей;
  • попытке переиспользования ephemeral ключа.

Эволюция подхода

ECDH-ES стал частью JOSE как развитие моделей:

  • RSA key transport → статичность и отсутствие forward secrecy;
  • ECDH-ES → динамическое согласование ключей;
  • X25519 → упрощённая и более быстрая реализация ECDH.

Современные реализации JavaScript-библиотек криптографии постепенно смещаются в сторону X25519 как наиболее удобного варианта ECDH-ES.