Чтение сертификата с помощью X509

Библиотека Jsrsasign предоставляет полноценный инструментарий для работы с криптографией в JavaScript, включая парсинг X.509 сертификатов, извлечение полей, проверку цепочек доверия и анализ расширений. Основной класс для работы с сертификатами — X509.


Форматы сертификатов: PEM и DER

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

PEM (Base64 с заголовками)

-----BEGIN CERTIFICATE-----
MIIDdzCCAl+gAwIBAgIEb1...
-----END CERTIFICATE-----
  • текстовый формат
  • используется в большинстве веб-серверов
  • легко передаётся через конфигурации и переменные среды

DER (бинарный формат)

  • бинарное представление ASN.1 структуры
  • чаще используется в низкоуровневых системах и хранилищах

Jsrsasign поддерживает оба формата, автоматически определяя тип при загрузке через X509.


Создание объекта X509

Для начала работы используется экземпляр класса X509:

const cert = new X509();

Далее сертификат загружается в объект.

Загрузка PEM

cert.readCertPEM(`
-----BEGIN CERTIFICATE-----
MIIDdzCCAl+gAwIBAgIEb1...
-----END CERTIFICATE-----
`);

Загрузка DER (hex)

cert.readCertHex("308203a..."); 

Структура X.509 сертификата

Сертификат X.509 включает несколько ключевых компонентов:

  • Subject — владелец сертификата
  • Issuer — удостоверяющий центр
  • Public Key — открытый ключ
  • Validity — срок действия
  • Serial Number — уникальный идентификатор
  • Extensions — дополнительные параметры

Jsrsasign позволяет извлекать каждый из этих элементов отдельно.


Извлечение Subject и Issuer

Subject (владелец сертификата)

const subject = cert.getSubjectString();

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

/C=US/O=Example Corp/CN=example.com

Issuer (центр сертификации)

const issuer = cert.getIssuerString();

Пример:

/C=US/O=Let's Encrypt/CN=R3

Серийный номер сертификата

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

const serial = cert.getSerialNumberHex();

Пример результата:

7a3f9c12ab45d901

Период действия сертификата

Сертификат всегда имеет ограниченный срок жизни.

Начало действия

const notBefore = cert.getNotBefore();

Окончание действия

const notAfter = cert.getNotAfter();

Формат обычно:

20240101000000Z
20250101000000Z

Алгоритм подписи

Определение алгоритма подписи важно для проверки доверия:

const alg = cert.getSignatureAlgorithmName();

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

  • SHA256withRSA
  • ECDSAwithSHA256

Получение открытого ключа

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

const pubKey = cert.getPublicKey();

Объект ключа можно использовать для:

  • проверки цифровых подписей
  • шифрования данных
  • построения TLS-цепочек

Проверка Subject Alternative Name (SAN)

Расширение SAN содержит альтернативные доменные имена:

const sans = cert.getExtSubjectAltName();

Пример результата:

DNS:example.com, DNS:www.example.com, IP:192.168.1.1

Проверка базовой валидности сертификата

Jsrsasign позволяет проверить соответствие сертификата текущей дате:

const isValidNow = cert.isValidOn(new Date());

Работа с расширениями сертификата

Расширения X.509 содержат дополнительные параметры:

  • Key Usage
  • Extended Key Usage
  • Subject Key Identifier
  • Authority Key Identifier

Пример извлечения:

const ext = cert.getExtKeyUsageString();

Результат:

serverAuth, clientAuth

Проверка подписи сертификата

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

const isVerified = cert.verifySignature(issuerPublicKey);

Где issuerPublicKey — публичный ключ центра сертификации.


Разбор цепочки сертификатов

В реальных системах сертификаты редко используются изолированно. Обычно они входят в цепочку:

  • Leaf certificate (серверный)
  • Intermediate CA
  • Root CA

Jsrsasign позволяет последовательно проверять каждый уровень, передавая публичные ключи вышестоящих центров.


Пример полного разбора сертификата

const cert = new X509();
cert.readCertPEM(pemString);

console.log(cert.getSubjectString());
console.log(cert.getIssuerString());
console.log(cert.getSerialNumberHex());
console.log(cert.getNotBefore());
console.log(cert.getNotAfter());
console.log(cert.getSignatureAlgorithmName());

const pubKey = cert.getPublicKey();
console.log(pubKey);

Особенности внутреннего парсинга

Jsrsasign работает с ASN.1 структурой сертификата. Внутренне происходит:

  • декодирование Base64 (если PEM)
  • парсинг ASN.1 дерева
  • извлечение TBSCertificate (to-be-signed part)
  • анализ signatureAlgorithm и signatureValue

Это обеспечивает корректное извлечение даже сложных расширений.


Обработка ошибок при чтении сертификата

При некорректном формате возможны ошибки:

  • неверные PEM-ограничители
  • повреждённый Base64
  • некорректная ASN.1 структура

Типичный подход:

try {
  cert.readCertPEM(pem);
} catch (e) {
  console.log("Ошибка разбора сертификата");
}

Практическое использование валидации данных сертификата

Извлечённые данные часто используются для:

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

Работа с публичными ключами внутри сертификата

Публичный ключ может быть RSA или EC:

const keyType = cert.getPublicKey().type;

Примеры:

  • RSA
  • EC

Извлечение всех полей сертификата

Для глубокого анализа используется полное декодирование:

const json = cert.getParam();

Это возвращает структурированное представление всех компонентов X.509.


Особенности работы с международными сертификатами

Некоторые сертификаты содержат:

  • IDN-домены
  • Unicode-имена организаций
  • расширенные политики

Jsrsasign корректно обрабатывает ASN.1 UTF8String и PrintableString, обеспечивая совместимость с глобальными PKI-системами.