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

Алгоритмы на основе эллиптических кривых (Elliptic Curve Cryptography, ECC) опираются на математические свойства точек на кривой вида:

y^2 = x^3 + ax + b

Безопасность схем строится на сложности задачи дискретного логарифмирования в группе точек кривой. В отличие от RSA, где ключи оперируют с большими числами, ECC обеспечивает сопоставимую криптостойкость при существенно меньших размерах ключей.

EC-ключ в контексте JavaScript-библиотеки Jsrsasign представляет собой пару:

  • приватный ключ (scalar, секретное число d)
  • публичный ключ (точка на кривой Q = dG)

где G — базовая точка генератора.

Публичный ключ кодируется как координаты точки (x, y), а приватный — как число фиксированной длины.

Поддерживаемые кривые и выбор параметров

В Jsrsasign используются стандартные именованные кривые, например:

  • secp256r1 (P-256)
  • secp256k1 (используется в блокчейн-системах)
  • secp384r1
  • secp521r1

Кривая определяет:

  • размер ключа
  • уровень криптостойкости
  • параметры уравнения эллиптической функции

На практике чаще всего используется secp256r1 как баланс между безопасностью и производительностью.

Генерация EC-ключей через KEYUTIL

Основной механизм генерации ключевых пар в Jsrsasign реализован через KEYUTIL.generateKeypair.

Базовый сценарий генерации EC-ключа:

const kp = KEYUTIL.generateKeypair("EC", "secp256r1");

const privateKey = kp.prvKeyObj;
const publicKey = kp.pubKeyObj;

Результатом является объект с двумя криптографическими сущностями:

  • prvKeyObj — приватный ключ
  • pubKeyObj — публичный ключ

Каждый из них может быть экспортирован в различные форматы.

Представление ключей в PEM-формате

Для взаимодействия с внешними системами ключи обычно сериализуются в PEM.

Приватный ключ:

const prvPEM = KEYUTIL.getPEM(privateKey, "PKCS8PRV");

Публичный ключ:

const pubPEM = KEYUTIL.getPEM(publicKey);

PEM-структура представляет собой Base64-кодированный DER-блок с заголовками:

-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----

и

-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----

Внутреннее устройство EC-ключей Jsrsasign

Внутри библиотеки EC-ключи представлены через объекты:

  • KJUR.crypto.ECDSA
  • KEYUTIL

Генерация включает несколько этапов:

  1. выбор параметров кривой (OID)
  2. генерация криптографически стойкого случайного числа d
  3. вычисление точки Q = dG
  4. упаковка в ASN.1 структуру

С точки зрения реализации:

const ec = new KJUR.crypto.ECDSA({ curve: "secp256r1" });

Однако прямое использование ECDSA для генерации ключей встречается реже, чем KEYUTIL.

Работа с криптографически стойкой случайностью

Ключевой элемент генерации — источник энтропии. Jsrsasign опирается на:

  • window.crypto в браузере
  • crypto модуль в Node.js

Если доступ к CSPRNG отсутствует, генерация становится небезопасной или невозможной.

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

После генерации доступны свойства ключей.

Приватный ключ:

console.log(privateKey.d.toString(16));

Публичный ключ:

console.log(publicKey.getX().toString(16));
console.log(publicKey.getY().toString(16));

Координаты X и Y представляют точку на эллиптической кривой.

Форматы экспорта и совместимость

Jsrsasign поддерживает несколько форматов:

  • PEM (PKCS#1 / PKCS#8)
  • DER
  • HEX
  • JSON-структуры

Пример экспорта в PKCS#8:

const pkcs8 = KEYUTIL.getPEM(privateKey, "PKCS8PRV");

Совместимость обеспечивается с:

  • OpenSSL
  • Java Keystore (через конвертацию)
  • WebCrypto API (частично)

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

EC-ключи чаще всего применяются для цифровой подписи.

Создание подписей:

const sig = new KJUR.crypto.Signature({ alg: "SHA256withECDSA" });
sig.init(privateKey);
sig.updateString("message");
const signature = sig.sign();

Проверка:

const ver = new KJUR.crypto.Signature({ alg: "SHA256withECDSA" });
ver.init(publicKey);
ver.updateString("message");
const isValid = ver.verify(signature);

Ключевая особенность ECC — компактность подписи при высокой стойкости.

Ошибки и типичные проблемы при генерации

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

Использование несуществующего OID приводит к ошибке генерации:

Unsupported EC curve

Отсутствие CSPRNG

При отсутствии криптографического источника случайности:

No secure random available

Неправильный формат экспорта

Попытка сериализации ключа без указания формата приводит к некорректному PEM.

Особенности производительности

Генерация EC-ключей значительно быстрее RSA благодаря:

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

На практике ключ EC-256 генерируется практически мгновенно даже в ограниченных средах исполнения JavaScript.

Взаимодействие с внешними криптосистемами

EC-ключи Jsrsasign часто используются в сценариях:

  • JWT (ES256)
  • TLS-эксперименты
  • Web3-подписи
  • API-аутентификация

При интеграции важно учитывать соответствие кривой и алгоритма подписи:

  • ES256 → secp256r1 + SHA-256
  • ES384 → secp384r1 + SHA-384

Несовпадение параметров делает подпись недействительной.

Формирование ключевой пары вручную

Хотя Jsrsasign генерирует ключи автоматически, структура EC-ключа концептуально сводится к:

  • выбору приватного числа d
  • вычислению публичной точки Q

Q = dG

где:

  • d — приватный ключ
  • G — генератор кривой
  • Q — публичный ключ

Эта формула лежит в основе всей EC-криптографии и напрямую отражается в работе Jsrsasign.