Структура открытого и закрытого ключа

Криптографические ключи в асимметричных алгоритмах представляют собой строго структурированные данные, описываемые не как произвольные строки, а как формализованные математические и ASN.1-конструкции. В контексте JavaScript-библиотеки Jsrsasign ключи рассматриваются через призму нескольких уровней представления: внутренние объекты алгоритмов, ASN.1-структуры, PEM-контейнеры и внешние стандарты PKCS и X.509.

Ключевой принцип асимметричной криптографии заключается в парности: открытый ключ используется для шифрования или проверки подписи, закрытый — для расшифрования или создания подписи. Однако на уровне реализации это не просто «два значения», а комплекс взаимосвязанных параметров.

Открытый ключ в RSA-системе математически сводится к двум основным компонентам:

  • модуль ( n )
  • открытая экспонента ( e )

RSA_{public} = (n, e)

В Jsrsasign этот набор обычно инкапсулируется в объект RSAKey, где публичные параметры доступны как свойства объекта или извлекаются через методы парсинга PEM/DER.

В стандарте X.509 публичный ключ не хранится «в чистом виде». Он упакован в структуру SubjectPublicKeyInfo:

  • алгоритм идентификации (OID RSA)
  • битовая строка, содержащая сам ключ

ASN.1-структура выглядит следующим образом:

SubjectPublicKeyInfo  ::=  SEQUENCE  {
    algorithm            AlgorithmIdentifier,
    subjectPublicKey     BIT STRING
}

В Jsrsasign разбор этой структуры выполняется через KEYUTIL.getKey(), который автоматически определяет формат и возвращает объект с удобным интерфейсом.

После декодирования BIT STRING для RSA извлекаются:

  • n (modulus)
  • e (public exponent)

Эти значения используются при операциях проверки подписи и шифрования.

Структура закрытого ключа RSA

Закрытый ключ RSA значительно более сложен. Он включает не только основной секретный показатель ( d ), но и дополнительные параметры для ускорения вычислений по теореме Китайской остатков:

  • ( n ) — модуль
  • ( e ) — открытая экспонента
  • ( d ) — закрытая экспонента
  • ( p, q ) — простые множители
  • ( dP = d (p-1) )
  • ( dQ = d (q-1) )
  • ( qInv = q^{-1} p )

RSA_{private} = (n, e, d, p, q, dP, dQ, qInv)

Эта структура соответствует стандарту PKCS#1 (RSAPrivateKey):

RSAPrivateKey ::= SEQUENCE {
    version           Version,
    modulus           INTEGER,
    publicExponent    INTEGER,
    privateExponent   INTEGER,
    prime1            INTEGER,
    prime2            INTEGER,
    exponent1         INTEGER,
    exponent2         INTEGER,
    coefficient       INTEGER
}

В Jsrsasign этот формат разбирается через ASN.1-парсеры KJUR.asn1 и затем преобразуется в объект RSAKey, где все параметры становятся доступными для операций подписи и расшифрования.

PKCS#1 и PKCS#8 как уровни упаковки

Закрытые ключи в реальных системах почти никогда не хранятся напрямую в формате RSAPrivateKey. Вместо этого используется контейнер PKCS#8:

PrivateKeyInfo ::= SEQUENCE {
    version                   Version,
    privateKeyAlgorithm       AlgorithmIdentifier,
    privateKey                OCTET STRING
}

PKCS#8 добавляет уровень абстракции:

  • идентификатор алгоритма
  • инкапсулированный приватный ключ (PKCS#1 внутри OCTET STRING)

Jsrsasign автоматически различает PKCS#1 и PKCS#8 при вызове:

  • KEYUTIL.getKey(pem)
  • KEYUTIL.getPEM(keyObj, "PKCS8PRV")

и выполняет вложенный разбор ASN.1 структуры.

PEM как текстовое представление

PEM-формат не является криптографической структурой. Это лишь Base64-кодированная упаковка DER-данных с заголовками:

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

или

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

Jsrsasign при обработке PEM выполняет:

  1. удаление заголовков
  2. декодирование Base64
  3. парсинг DER через ASN.1 декодер

Таким образом PEM — это внешний слой, а реальная структура находится внутри DER.

Внутреннее представление в Jsrsasign

Библиотека Jsrsasign использует объект RSAKey как центральную модель RSA-ключа. Его поля включают:

  • n — BigInteger модуль
  • e — открытая экспонента
  • d — закрытая экспонента
  • p, q — факторы
  • isPrivate — флаг наличия приватной части

Дополнительно присутствуют оптимизационные параметры CRT:

  • dmp1
  • dmq1
  • coeff

Эти поля позволяют ускорять операции подписи:

m_1 = m p,m_2 = m q

и последующее объединение результатов через китайскую теорему остатков.

Структура открытого ключа в ECDSA

Для эллиптических кривых структура отличается принципиально. Открытый ключ состоит из:

  • точки ( (x, y) ) на кривой
  • параметров кривой (secp256r1, secp256k1 и др.)

Q = d G

где:

  • ( d ) — закрытый ключ
  • ( G ) — базовая точка
  • ( Q ) — открытый ключ

В Jsrsasign ECDSA-ключи представляются через объект KJUR.crypto.ECDSA, а параметры извлекаются из PKCS#8 или SEC1 форматов.

SEC1 структура приватного ключа включает:

ECPrivateKey ::= SEQUENCE {
    version        INTEGER,
    privateKey     OCTET STRING,
    parameters     [0] EXPLICIT ECParameters OPTIONAL,
    publicKey      [1] EXPLICIT BIT STRING OPTIONAL
}

DER как бинарная основа всех ключей

DER (Distinguished Encoding Rules) — это бинарная форма ASN.1. Все ключевые структуры (PKCS#1, PKCS#8, X.509) в конечном итоге кодируются в DER.

В Jsrsasign именно DER является промежуточным слоем между:

  • текстовым PEM
  • объектной моделью ключа

Парсинг DER осуществляется через ASN.1-дерево, где каждый узел имеет:

  • tag
  • length
  • value

JWK как альтернативная модель

Помимо ASN.1 существует JSON Web Key (JWK), где структура ключа выражается JSON-объектом:

RSA:

{
  "kty": "RSA",
  "n": "...",
  "e": "...",
  "d": "...",
  "p": "...",
  "q": "..."
}

В Jsrsasign присутствует конвертация:

  • PEM → JWK
  • JWK → RSAKey

JWK упрощает интеграцию с web-API, но не заменяет ASN.1 внутри криптографического ядра.

Связь структур и операций подписи

Структура ключа напрямую влияет на алгоритмы:

  • открытый ключ используется в проверке:

s^e n

  • закрытый ключ используется в подписи:

m^d n

CRT-оптимизация позволяет выполнять операции быстрее за счёт разбиения модуля на простые множители.

Разбор ключа через KEYUTIL

В Jsrsasign центральная точка входа для работы с ключами:

var key = KEYUTIL.getKey(pemString);

После этого объект может содержать:

  • публичные параметры
  • приватные параметры
  • тип алгоритма

Функция автоматически:

  • определяет PEM-тип
  • декодирует Base64
  • парсит ASN.1
  • собирает RSAKey или ECDSAKey

Иерархия представлений ключа

Структура ключа в Jsrsasign проходит несколько уровней:

  1. PEM (строковый контейнер)
  2. DER (бинарный ASN.1)
  3. PKCS#1 / PKCS#8 / SPKI (логическая структура)
  4. RSAKey / ECDSAKey (объект библиотеки)
  5. математические операции (mod exp, scalar multiplication)

Эта цепочка обеспечивает совместимость между криптографическими стандартами и JavaScript-реализацией.

Взаимосвязь параметров RSA

Каждый элемент закрытого ключа связан с другими математическими соотношениями:

d e

где:

  • ( (n) = (p-1)(q-1) )

Эта зависимость гарантирует корректность восстановления исходного сообщения при расшифровании.


Структура ключей в Jsrsasign представляет собой многоуровневую систему, где каждый уровень — от ASN.1 до объектной модели JavaScript — отражает строго определённые криптографические стандарты и математические зависимости.