Получение subject и issuer

В X.509 сертификате ключевые идентификационные поля представлены через Distinguished Name (DN), которые описывают субъект (subject) и издателя (issuer). Эти структуры содержат набор атрибутов, таких как Common Name (CN), Organization (O), Organizational Unit (OU), Country (C) и другие.

В контексте JavaScript-библиотеки jsrsasign работа с этими полями выполняется через объект X509, который предоставляет методы для разбора PEM-сертификата и извлечения данных в удобном формате.


Разбор PEM-сертификата

Перед получением subject и issuer сертификат необходимо загрузить и разобрать:

const certPEM = `
-----BEGIN CERTIFICATE-----
MIIC...
-----END CERTIFICATE-----
`;

const x509 = new X509();
x509.readCertPEM(certPEM);

После вызова readCertPEM объект сертификата становится доступным для анализа.


Получение строкового представления Subject и Issuer

Самый простой способ извлечения данных — использование строковых методов.

const subjectStr = x509.getSubjectString();
const issuerStr = x509.getIssuerString();

console.log(subjectStr);
console.log(issuerStr);

Результат обычно выглядит как DN-строка:

CN=example.com, O=Example Corp, C=US
CN=Let's Encrypt Authority X3, O=Let's Encrypt, C=US

Эти методы полезны для быстрого отображения информации без дополнительной обработки.


Структурированное получение Subject

Для более глубокой работы используется метод, возвращающий структурированное представление DN.

const subject = x509.getSubject();

Результат представляет собой объект с массивом атрибутов:

{
  array: [
    { type: "CN", value: "example.com" },
    { type: "O", value: "Example Corp" },
    { type: "C", value: "US" }
  ]
}

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


Разбор структуры Subject

Обработка DN сводится к итерации по массиву:

const subject = x509.getSubject();

subject.array.forEach(attr => {
  console.log(attr.type + " = " + attr.value);
});

Типы атрибутов соответствуют стандарту X.509:

  • CN — Common Name
  • O — Organization
  • OU — Organizational Unit
  • C — Country
  • L — Locality
  • ST — State or Province

Получение Issuer в структурированном виде

Issuer извлекается аналогичным способом:

const issuer = x509.getIssuer();

Структура полностью идентична subject:

{
  array: [
    { type: "CN", value: "R3" },
    { type: "O", value: "Let's Encrypt" },
    { type: "C", value: "US" }
  ]
}

Сравнение Subject и Issuer

Subject описывает владельца сертификата, тогда как issuer указывает центр сертификации, который его подписал.

Пример сопоставления:

const subject = x509.getSubject();
const issuer = x509.getIssuer();

const subjectCN = subject.array.find(x => x.type === "CN")?.value;
const issuerCN = issuer.array.find(x => x.type === "CN")?.value;

Такой подход позволяет анализировать цепочки доверия и проверять соответствие сертификатов.


Извлечение отдельных атрибутов DN

Часто требуется получить конкретное поле без обхода массива:

function getDNValue(dn, type) {
  const item = dn.array.find(x => x.type === type);
  return item ? item.value : null;
}

const cn = getDNValue(x509.getSubject(), "CN");
const country = getDNValue(x509.getSubject(), "C");

Этот подход упрощает работу с сертификатами в прикладных сценариях, таких как проверка домена или региона.


Работа с вложенными DN и многоуровневыми значениями

DN может содержать повторяющиеся атрибуты:

{
  array: [
    { type: "OU", value: "IT" },
    { type: "OU", value: "Security" }
  ]
}

Обработка всех значений выполняется без предположения уникальности:

const ous = x509.getSubject().array
  .filter(x => x.type === "OU")
  .map(x => x.value);

Сравнение сертификатов по Subject и Issuer

Для проверки идентичности сертификатов часто используется сопоставление DN:

function dnToString(dn) {
  return dn.array
    .map(x => `${x.type}=${x.value}`)
    .join(", ");
}

const subjectA = dnToString(x509.getSubject());
const issuerA = dnToString(x509.getIssuer());

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


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

Библиотека jsrsasign использует ASN.1-парсинг для преобразования DER-структуры сертификата в JavaScript-объекты. Distinguished Name разбирается как последовательность Relative Distinguished Names (RDN), каждый из которых может содержать один или несколько атрибутов.

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


Типичные сценарии использования Subject и Issuer

В прикладной разработке данные поля используются для:

  • проверки доменного имени в CN или SAN
  • идентификации организации-владельца сертификата
  • построения цепочек доверия
  • аудита и логирования TLS-соединений
  • фильтрации сертификатов по стране или региону

Обработка отсутствующих полей

Некоторые сертификаты могут не содержать всех атрибутов:

const subject = x509.getSubject();

const org = subject.array.find(x => x.type === "O");
const orgValue = org ? org.value : "unknown";

Корректная обработка отсутствующих значений критична при работе с разнородными сертификатами.


Нормализация значений DN

Для унификации данных часто выполняется нормализация:

function normalizeDN(dn) {
  return dn.array.reduce((acc, x) => {
    acc[x.type] = (acc[x.type] || []).concat(x.value);
    return acc;
  }, {});
}

const normalizedSubject = normalizeDN(x509.getSubject());

Результат:

{
  CN: ["example.com"],
  O: ["Example Corp"],
  C: ["US"]
}

Использование валидации через Subject и Issuer

Проверка цепочки сертификатов может включать сравнение issuer одного сертификата с subject следующего:

const isChainValid = dnToString(certA.getIssuer()) === dnToString(certB.getSubject());

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