Добавление расширений при построении

В структуре X.509 расширения (extensions) определяют дополнительные атрибуты сертификата, выходящие за рамки базовых полей субъекта и ключа. В контексте Jsrsasign работа с расширениями выполняется на этапе построения сертификата и влияет на итоговую ASN.1-структуру, включаемую в подпись.

Расширения кодируются в поле extensions объекта сертификата и формируются через специализированные ASN.1-конструкторы библиотеки KJUR.asn1.x509.


Архитектура расширений в Jsrsasign

Расширения представляют собой массив объектов, где каждый элемент описывает отдельное расширение:

  • идентификатор расширения (extname или ext)
  • признак критичности (critical)
  • значение расширения (value или ASN.1 структура)

Общий принцип построения:

ext: [
  {
    extname: "keyUsage",
    critical: true,
    names: ["digitalSignature", "keyEncipherment"]
  }
]

Каждое расширение преобразуется в DER-представление внутри сертификата.


Механизм подключения расширений при построении сертификата

При создании сертификата через KJUR.asn1.x509.Certificate расширения передаются в параметре конфигурации:

const cert = new KJUR.asn1.x509.Certificate({
  version: 3,
  serial: { hex: "01" },
  sigalg: "SHA256withRSA",
  issuer: { str: "/C=US/O=Example CA" },
  notbefore: "230101000000Z",
  notafter:  "240101000000Z",
  subject: { str: "/C=US/O=Example" },
  sbjpubkey: pubKeyObj,
  ext: [
    {
      extname: "basicConstraints",
      cA: false
    }
  ]
});

Внутри процесса построения сертификата Jsrsasign вызывает генераторы ASN.1 для каждого расширения и формирует структуру:

  • Extension OID
  • Critical flag
  • OCTET STRING с закодированным значением

BasicConstraints

Расширение basicConstraints определяет, является ли сертификат удостоверяющим центром.

ext: [
  {
    extname: "basicConstraints",
    cA: true,
    pathLen: 2
  }
]

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

  • cA: true — сертификат CA
  • pathLen ограничивает глубину цепочки

ASN.1 структура формируется через KJUR.asn1.x509.BasicConstraints.


KeyUsage

Расширение определяет допустимые операции с ключом.

ext: [
  {
    extname: "keyUsage",
    critical: true,
    names: [
      "digitalSignature",
      "keyEncipherment",
      "keyCertSign"
    ]
  }
]

Поддерживаемые значения:

  • digitalSignature
  • nonRepudiation
  • keyEncipherment
  • dataEncipherment
  • keyAgreement
  • keyCertSign
  • cRLSign

Каждое значение кодируется в битовую маску ASN.1 BIT STRING.


ExtendedKeyUsage

Используется для уточнения сценариев применения ключа.

ext: [
  {
    extname: "extKeyUsage",
    array: [
      "serverAuth",
      "clientAuth"
    ]
  }
]

Примеры значений:

  • serverAuth (TLS сервер)
  • clientAuth (TLS клиент)
  • codeSigning
  • emailProtection

Subject Alternative Name

Расширение SAN позволяет привязать дополнительные идентификаторы к сертификату.

ext: [
  {
    extname: "subjectAltName",
    array: [
      { dns: "example.com" },
      { dns: "api.example.com" },
      { ip: "192.168.1.10" }
    ]
  }
]

Поддерживаются типы:

  • DNS
  • IP
  • email
  • URI

В ASN.1 формируется структура GeneralNames.


Authority Key Identifier и Subject Key Identifier

Используются для построения цепочек доверия.

ext: [
  {
    extname: "subjectKeyIdentifier"
  },
  {
    extname: "authorityKeyIdentifier",
    keyid: "auto"
  }
]

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

  • subjectKeyIdentifier генерируется из публичного ключа
  • authorityKeyIdentifier связывает сертификат с издателем

Custom OID расширения

Jsrsasign позволяет добавлять произвольные расширения через OID.

ext: [
  {
    ext: "1.2.3.4.5.6",
    critical: false,
    value: {
      hex: "0c0a48656c6c6f576f726c64"
    }
  }
]

Используется:

  • для приватных политик
  • корпоративных атрибутов
  • нестандартных метаданных

Кодирование расширений в ASN.1

Каждое расширение преобразуется в структуру:

Extension ::= SEQUENCE {
  extnID      OBJECT IDENTIFIER,
  critical    BOOLEAN DEFAULT FALSE,
  extnValue   OCTET STRING
}

Jsrsasign выполняет двойное кодирование:

  1. создание внутреннего ASN.1 объекта
  2. упаковка результата в OCTET STRING

Это критично для совместимости с OpenSSL и браузерными валидаторами.


Управление критичностью расширений

Поле critical влияет на поведение валидаторов сертификата:

  • true — обязательная поддержка расширения
  • false — может игнорироваться

Пример:

ext: [
  {
    extname: "keyUsage",
    critical: true,
    names: ["digitalSignature"]
  }
]

Если критическое расширение не поддерживается клиентом, сертификат считается недействительным.


Взаимодействие расширений между собой

Некоторые расширения логически связаны:

  • basicConstraints определяет роль CA
  • keyUsage должен включать keyCertSign для CA
  • subjectAltName заменяет использование CN в современных TLS

Несоответствие приводит к ошибкам в цепочке доверия при проверке через OpenSSL или браузеры.


Пример комплексной конфигурации

const cert = new KJUR.asn1.x509.Certificate({
  version: 3,
  serial: { int: 1000 },
  sigalg: "SHA256withRSA",
  issuer: { str: "/C=US/O=Root CA" },
  subject: { str: "/C=US/O=Service" },
  sbjpubkey: pubKeyObj,
  notbefore: "250101000000Z",
  notafter: "260101000000Z",
  ext: [
    {
      extname: "basicConstraints",
      cA: false
    },
    {
      extname: "keyUsage",
      critical: true,
      names: ["digitalSignature", "keyEncipherment"]
    },
    {
      extname: "subjectAltName",
      array: [
        { dns: "service.local" }
      ]
    }
  ]
});

Особенности внутренней обработки Jsrsasign

При построении сертификата выполняется последовательность:

  1. Валидация входных параметров расширений
  2. Преобразование в ASN.1 объекты через KJUR.asn1.x509.*
  3. Упаковка в Extensions SEQUENCE
  4. Встраивание в TBSCertificate
  5. Подпись итоговой структуры

Ошибки на уровне расширений приводят к сбоям на этапе DER-кодирования до формирования подписи.


Ограничения и совместимость

  • не все расширения одинаково поддерживаются различными криптографическими библиотеками
  • строгие валидаторы требуют корректного OID и DER-кодирования
  • порядок расширений не влияет на криптографическую корректность, но может влиять на диагностику

Особенно критично:

  • правильное кодирование SAN
  • соответствие KeyUsage роли сертификата
  • корректный BasicConstraints для CA