DSA: генерация ключей и параметры

В криптосистеме DSA (Digital Signature Algorithm) ключевая пара состоит из приватного ключа x и публичного ключа y, которые вычисляются на основе параметров домена: простого числа p, подгруппы q и генератора g. В Jsrsasign работа с этими параметрами скрыта за высокоуровневыми API, но при необходимости их можно задавать явно и контролировать процесс генерации.

В библиотеке Jsrsasign генерация ключей DSA реализуется через KEYUTIL.generateKeypair, а также через низкоуровневые криптографические классы KJUR.crypto.

Основные параметры DSA

DSA требует заранее определённого набора доменных параметров:

  • p — большое простое число (обычно 1024–3072 бит)
  • q — 160–256-битное простое число, делитель p − 1
  • g — генератор подгруппы порядка q в поле mod p
  • x — приватный ключ (0 < x < q)
  • y — публичный ключ: y = g^x mod p

y = g^x p

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


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

Jsrsasign предоставляет высокоуровневую функцию, которая автоматически генерирует параметры и ключи:

const kp = KEYUTIL.generateKeypair("DSA", 2048);

В этом случае:

  • DSA — алгоритм
  • 2048 — размер p (битность)

Библиотека самостоятельно подбирает параметры q и g в соответствии со стандартами FIPS 186-4.

Результат содержит объект:

{
  prvKeyObj: ...,
  pubKeyObj: ...
}

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

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

const prv = kp.prvKeyObj;
const pub = kp.pubKeyObj;

Дальнейшая работа происходит через методы объектов:

  • prv.sign(...)
  • pub.verify(...)

или через сериализацию в PEM:

const prvPEM = KEYUTIL.getPEM(prv, "PKCS8PRV");
const pubPEM = KEYUTIL.getPEM(pub);

Явная генерация с контролем параметров

Jsrsasign позволяет задать параметры домена вручную, что важно для совместимости с внешними системами.

Пример задания параметров:

const param = {
  p: "FCA682CE8E12CABA26EFCCF7110E526DB078B05EDECBCD1E...",
  q: "962EDDCC369CBA8E1A3",
  g: "678471B27A9CF44BD9F0A2E1..."
};

Генерация ключа с параметрами:

const kp = KEYUTIL.generateKeypair("DSA", 2048, param);

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


Внутренний процесс генерации

При создании DSA ключей Jsrsasign выполняет несколько шагов:

  1. Генерация или принятие параметров p, q, g
  2. Генерация случайного числа x
  3. Вычисление публичного ключа y

x (0, q)

y = g^x p

Качество случайного числа x критично для безопасности. Jsrsasign использует криптографически стойкий генератор случайных чисел (CSPRNG), встроенный в среду выполнения (Node.js или браузер).


Работа с классом DSAKey

Низкоуровневый доступ предоставляется через:

const dsa = new KJUR.crypto.DSAKey();

Далее можно задать параметры вручную:

dsa.setPublic(p, q, g, y);
dsa.setPrivate(x);

или использовать генерацию:

dsa.generateKeyPair();

Этот подход полезен при отладке или интеграции с нестандартными криптосистемами.


Размеры ключей и безопасность

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

  • 1024 бит — устаревший, но встречается в легаси-системах
  • 2048 бит — минимально рекомендуемый
  • 3072 бит — повышенная безопасность

Размер q обычно:

  • 160 бит (старые схемы)
  • 224/256 бит (современные варианты)

Связь между параметрами влияет на криптостойкость и скорость операций подписи.


Сериализация ключей

После генерации ключи можно экспортировать в стандартизированные форматы:

PKCS#8 (приватный ключ)

const pemPrv = KEYUTIL.getPEM(kp.prvKeyObj, "PKCS8PRV");

X.509 (публичный ключ)

const pemPub = KEYUTIL.getPEM(kp.pubKeyObj);

Форматирование происходит с ASN.1 структурированием внутри библиотеки.


Преобразование ключей из PEM

Jsrsasign поддерживает обратную операцию:

const keyObj = KEYUTIL.getKey(pemString);

Если PEM содержит DSA ключ, объект автоматически приводится к типу DSAKey.


Влияние параметров на подпись

DSA-подпись зависит не только от ключей, но и от выбранного хэш-алгоритма.

В Jsrsasign обычно используются:

  • SHA-1 (устаревший)
  • SHA-256 (рекомендуемый)
  • SHA-384/512 (для увеличенной стойкости)

Подпись формируется как пара значений (r, s), вычисляемых через модульные операции.


Формирование доменных параметров вручную

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

Пример структуры:

const dsa = new KJUR.crypto.DSAKey();
dsa.generateParams(2048, 256);

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


Ошибки и ограничения генерации

При работе с DSA в Jsrsasign часто встречаются ограничения:

  • неподходящая длина q для выбранного p
  • использование слабого CSPRNG в среде выполнения
  • несовместимость параметров с внешними реализациями OpenSSL

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


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

В отличие от низкоуровневых библиотек, Jsrsasign:

  • абстрагирует генерацию параметров
  • автоматически валидирует структуру ключей
  • поддерживает экспорт в несколько стандартов
  • интегрирует криптографические операции с ASN.1 представлением

Это делает DSA в Jsrsasign пригодным для прикладных задач, но менее гибким на уровне тонкой криптографической настройки по сравнению с OpenSSL.